2 This file is part of GNUnet.
3 (C) 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 Licerevocation 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 Licerevocation for more details.
15 You should have received a copy of the GNU General Public Licerevocation
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 revocation/gnunet-service-revocation.c
23 * @brief key revocation service
24 * @author Christian Grothoff
26 * The purpose of this service is to allow users to permanently revoke
27 * (compromised) keys. This is done by flooding the network with the
28 * revocation requests. To reduce the attack potential offered by such
29 * flooding, revocations must include a proof of work. We use the
30 * set service for efficiently computing the union of revocations of
34 * - load revocations from disk
35 * - store revocations to disk
36 * - handle p2p revocations
37 * - handle p2p connect (trigger SET union)
38 * - handle client revoke message
39 * - handle client query message
43 #include "gnunet_util_lib.h"
44 #include "gnunet_constants.h"
45 #include "gnunet_protocols.h"
46 #include "gnunet_signatures.h"
47 #include "gnunet_statistics_service.h"
48 #include "gnunet_core_service.h"
49 #include "gnunet_revocation_service.h"
50 #include "gnunet_set_service.h"
51 #include "revocation.h"
56 * Per-peer information.
62 * Core handle for sending messages to this peer.
64 struct GNUNET_CORE_TransmitHandle *th;
67 * What is the identity of the peer?
69 struct GNUNET_PeerIdentity id;
72 * Task scheduled to send message to this peer.
74 GNUNET_SCHEDULER_TaskIdentifier transmit_task;
80 * Set from all revocations known to us.
82 static struct GNUNET_SET_Handle *revocation_set;
85 * Handle to our current configuration.
87 static const struct GNUNET_CONFIGURATION_Handle *cfg;
90 * Handle to the statistics service.
92 static struct GNUNET_STATISTICS_Handle *stats;
95 * Handle to the core service (for flooding)
97 static struct GNUNET_CORE_Handle *coreAPI;
100 * Map of all connected peers.
102 static struct GNUNET_CONTAINER_MultiPeerMap *peers;
105 * The peer identity of this peer.
107 static struct GNUNET_PeerIdentity my_identity;
110 * Handle to this serivce's server.
112 static struct GNUNET_SERVER_Handle *srv;
115 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits.
117 static unsigned long long revocation_work_required;
121 * An revoke message has been received, check that it is well-formed.
123 * @param rm the message to verify
124 * @return #GNUNET_YES if the message is verified
125 * #GNUNET_NO if the key/signature don't verify
128 verify_revoke_message (const struct RevokeMessage *rm)
131 GNUNET_REVOCATION_check_pow (&rm->public_key,
133 (unsigned int) revocation_work_required))
135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
136 "Proof of work invalid: %llu!\n",
138 GNUNET_ntohll (rm->proof_of_work));
143 GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_REVOCATION,
156 * Handle QUERY message from client.
159 * @param client who sent the message
160 * @param message the message received
163 handle_query_message (void *cls,
164 struct GNUNET_SERVER_Client *client,
165 const struct GNUNET_MessageHeader *message)
167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
168 "Received QUERY message from client\n");
170 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
175 * Handle REVOKE message from client.
178 * @param client who sent the message
179 * @param message the message received
182 handle_revoke_message (void *cls,
183 struct GNUNET_SERVER_Client *client,
184 const struct GNUNET_MessageHeader *message)
186 const struct RevokeMessage *rm;
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Received REVOKE message from client\n");
190 rm = (const struct RevokeMessage *) message;
192 verify_revoke_message (rm))
195 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
197 GNUNET_break (0); // FIXME: TBD
198 GNUNET_SERVER_receive_done (client, GNUNET_OK);
203 * Core handler for flooded revocation messages.
205 * @param cls closure unused
206 * @param message message
207 * @param peer peer identity this message is from (ignored)
210 handle_p2p_revoke_message (void *cls,
211 const struct GNUNET_PeerIdentity *peer,
212 const struct GNUNET_MessageHeader *message)
214 const struct RevokeMessage *rm;
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
218 "Received REVOKE message from peer\n");
219 rm = (const struct RevokeMessage *) message;
221 verify_revoke_message (rm))
224 return GNUNET_SYSERR;
226 GNUNET_break (0); // FIXME: TBD
230 GNUNET_CONTAINER_multipeermap_iterate (peers,
239 * Method called whenever a peer connects. Sets up the PeerEntry and
240 * schedules the initial revocation set exchange with this peer.
243 * @param peer peer identity this notification is about
246 handle_core_connect (void *cls,
247 const struct GNUNET_PeerIdentity *peer)
249 struct PeerEntry *peer_entry;
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n",
253 peer_entry = GNUNET_new (struct PeerEntry);
254 peer_entry->id = *peer;
255 GNUNET_assert (GNUNET_OK ==
256 GNUNET_CONTAINER_multipeermap_put (peers, peer,
258 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
260 peer_entry->transmit_task =
261 GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb,
264 GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO);
269 * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
270 * any pending transmission requests to that peer.
273 * @param peer peer identity this notification is about
276 handle_core_disconnect (void *cls,
277 const struct GNUNET_PeerIdentity *peer)
279 struct PeerEntry *pos;
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
282 "Peer `%s' disconnected from us\n",
284 pos = GNUNET_CONTAINER_multipeermap_get (peers, peer);
290 GNUNET_assert (GNUNET_YES ==
291 GNUNET_CONTAINER_multipeermap_remove (peers, peer,
294 if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK)
296 GNUNET_SCHEDULER_cancel (pos->transmit_task);
297 pos->transmit_task = GNUNET_SCHEDULER_NO_TASK;
301 GNUNET_CORE_notify_transmit_ready_cancel (pos->th);
306 GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO);
311 * Task run during shutdown.
317 shutdown_task (void *cls,
318 const struct GNUNET_SCHEDULER_TaskContext *tc)
320 if (NULL != revocation_set)
322 GNUNET_SET_destroy (revocation_set);
323 revocation_set = NULL;
327 GNUNET_CORE_disconnect (coreAPI);
332 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
337 GNUNET_CONTAINER_multipeermap_destroy (peers);
344 * Called on core init/fail.
346 * @param cls service closure
347 * @param identity the public identity of this peer
350 core_init (void *cls,
351 const struct GNUNET_PeerIdentity *identity)
353 if (NULL == identity)
355 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
356 "Connection to core FAILED!\n");
357 GNUNET_SCHEDULER_shutdown ();
360 my_identity = *identity;
365 * Handle network size estimate clients.
368 * @param server the initialized server
369 * @param c configuration to use
373 struct GNUNET_SERVER_Handle *server,
374 const struct GNUNET_CONFIGURATION_Handle *c)
376 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
377 {&handle_query_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
378 sizeof (struct QueryMessage)},
379 {&handle_revoke_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
380 sizeof (struct RevokeMessage)},
383 static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
384 {&handle_p2p_revoke_message, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
385 sizeof (struct RevokeMessage)},
392 GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS",
393 &revocation_work_required))
395 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
398 GNUNET_SCHEDULER_shutdown ();
401 if (revocation_work_required >= sizeof (struct GNUNET_HashCode) * 8)
403 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
406 _("Value is too large.\n"));
407 GNUNET_SCHEDULER_shutdown ();
410 revocation_set = GNUNET_SET_create (cfg,
411 GNUNET_SET_OPERATION_UNION);
412 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
414 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
415 GNUNET_SERVER_add_handlers (srv, handlers);
416 /* Connect to core service and register core handlers */
417 coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */
418 NULL, /* Closure passed to functions */
419 &core_init, /* Call core_init once connected */
420 &handle_core_connect, /* Handle connects */
421 &handle_core_disconnect, /* Handle disconnects */
422 NULL, /* Don't want notified about all incoming messages */
423 GNUNET_NO, /* For header only inbound notification */
424 NULL, /* Don't want notified about all outbound messages */
425 GNUNET_NO, /* For header only outbound notification */
426 core_handlers); /* Register these handlers */
429 GNUNET_SCHEDULER_shutdown ();
432 stats = GNUNET_STATISTICS_create ("revocation", cfg);
437 * The main function for the network size estimation service.
439 * @param argc number of arguments from the command line
440 * @param argv command line arguments
441 * @return 0 ok, 1 on error
448 GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE,
449 &run, NULL)) ? 0 : 1;
457 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
459 void __attribute__ ((constructor))
460 GNUNET_ARM_memory_init ()
462 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
463 mallopt (M_TOP_PAD, 1 * 1024);
470 /* end of gnunet-service-revocation.c */