diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-09-20 19:53:24 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-09-20 19:53:24 +0000 |
commit | 03f0ae4bb10cf55bb9bab601d45fd96c2eb13603 (patch) | |
tree | 9089fc11319e7de97c43d2e0bf8e6d9b67836b92 /src/transport/gnunet-service-transport_blacklist.c | |
parent | 450982bb56fde81bd512cb21360b809482caf19b (diff) | |
download | gnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.tar.gz gnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.zip |
migrating transport service to new MQ API
Diffstat (limited to 'src/transport/gnunet-service-transport_blacklist.c')
-rw-r--r-- | src/transport/gnunet-service-transport_blacklist.c | 933 |
1 files changed, 0 insertions, 933 deletions
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c deleted file mode 100644 index b6c36a6cd..000000000 --- a/src/transport/gnunet-service-transport_blacklist.c +++ /dev/null | |||
@@ -1,933 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010,2011 GNUnet e.V. | ||
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 3, 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., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file transport/gnunet-service-transport_blacklist.c | ||
23 | * @brief blacklisting implementation | ||
24 | * @author Christian Grothoff | ||
25 | * @author Matthias Wachs | ||
26 | * @details This is the blacklisting component of transport service. With | ||
27 | * blacklisting it is possible to deny connections to specific peers of | ||
28 | * to use a specific plugin to a specific peer. Peers can be blacklisted using | ||
29 | * the configuration or a blacklist client can be asked. | ||
30 | * | ||
31 | * To blacklist peers using the configuration you have to add a section to your | ||
32 | * configuration containing the peer id of the peer to blacklist and the plugin | ||
33 | * if required. | ||
34 | * | ||
35 | * Example: | ||
36 | * To blacklist connections to P565... on peer AG2P... using tcp add: | ||
37 | * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520] | ||
38 | * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = tcp | ||
39 | * | ||
40 | * To blacklist connections to P565... on peer AG2P... using all plugins add: | ||
41 | * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520] | ||
42 | * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = | ||
43 | * | ||
44 | * You can also add a blacklist client usign the blacklist api. On a blacklist | ||
45 | * check, blacklisting first checks internally if the peer is blacklisted and | ||
46 | * if not, it asks the blacklisting clients. Clients are asked if it is OK to | ||
47 | * connect to a peer ID, the plugin is omitted. | ||
48 | * | ||
49 | * On blacklist check for (peer, plugin) | ||
50 | * - Do we have a local blacklist entry for this peer and this plugin? | ||
51 | * - YES: disallow connection | ||
52 | * - Do we have a local blacklist entry for this peer and all plugins? | ||
53 | * - YES: disallow connection | ||
54 | * - Does one of the clients disallow? | ||
55 | * - YES: disallow connection | ||
56 | * | ||
57 | */ | ||
58 | #include "platform.h" | ||
59 | #include "gnunet-service-transport.h" | ||
60 | #include "gnunet-service-transport_blacklist.h" | ||
61 | #include "gnunet-service-transport_neighbours.h" | ||
62 | #include "transport.h" | ||
63 | |||
64 | /** | ||
65 | * Size of the blacklist hash map. | ||
66 | */ | ||
67 | #define TRANSPORT_BLACKLIST_HT_SIZE 64 | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Context we use when performing a blacklist check. | ||
72 | */ | ||
73 | struct GST_BlacklistCheck; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Information kept for each client registered to perform | ||
78 | * blacklisting. | ||
79 | */ | ||
80 | struct Blacklisters | ||
81 | { | ||
82 | /** | ||
83 | * This is a linked list. | ||
84 | */ | ||
85 | struct Blacklisters *next; | ||
86 | |||
87 | /** | ||
88 | * This is a linked list. | ||
89 | */ | ||
90 | struct Blacklisters *prev; | ||
91 | |||
92 | /** | ||
93 | * Client responsible for this entry. | ||
94 | */ | ||
95 | struct GNUNET_SERVER_Client *client; | ||
96 | |||
97 | /** | ||
98 | * Blacklist check that we're currently performing (or NULL | ||
99 | * if we're performing one that has been cancelled). | ||
100 | */ | ||
101 | struct GST_BlacklistCheck *bc; | ||
102 | |||
103 | /** | ||
104 | * Set to #GNUNET_YES if we're currently waiting for a reply. | ||
105 | */ | ||
106 | int waiting_for_reply; | ||
107 | |||
108 | /** | ||
109 | * #GNUNET_YES if we have to call receive_done for this client | ||
110 | */ | ||
111 | int call_receive_done; | ||
112 | |||
113 | }; | ||
114 | |||
115 | |||
116 | |||
117 | /** | ||
118 | * Context we use when performing a blacklist check. | ||
119 | */ | ||
120 | struct GST_BlacklistCheck | ||
121 | { | ||
122 | |||
123 | /** | ||
124 | * This is a linked list. | ||
125 | */ | ||
126 | struct GST_BlacklistCheck *next; | ||
127 | |||
128 | /** | ||
129 | * This is a linked list. | ||
130 | */ | ||
131 | struct GST_BlacklistCheck *prev; | ||
132 | |||
133 | /** | ||
134 | * Peer being checked. | ||
135 | */ | ||
136 | struct GNUNET_PeerIdentity peer; | ||
137 | |||
138 | /** | ||
139 | * Continuation to call with the result. | ||
140 | */ | ||
141 | GST_BlacklistTestContinuation cont; | ||
142 | |||
143 | /** | ||
144 | * Closure for @e cont. | ||
145 | */ | ||
146 | void *cont_cls; | ||
147 | |||
148 | /** | ||
149 | * Address for #GST_blacklist_abort_matching(), can be NULL. | ||
150 | */ | ||
151 | struct GNUNET_HELLO_Address *address; | ||
152 | |||
153 | /** | ||
154 | * Session for #GST_blacklist_abort_matching(), can be NULL. | ||
155 | */ | ||
156 | struct GNUNET_ATS_Session *session; | ||
157 | |||
158 | /** | ||
159 | * Current transmission request handle for this client, or NULL if no | ||
160 | * request is pending. | ||
161 | */ | ||
162 | struct GNUNET_SERVER_TransmitHandle *th; | ||
163 | |||
164 | /** | ||
165 | * Our current position in the blacklisters list. | ||
166 | */ | ||
167 | struct Blacklisters *bl_pos; | ||
168 | |||
169 | /** | ||
170 | * Current task performing the check. | ||
171 | */ | ||
172 | struct GNUNET_SCHEDULER_Task *task; | ||
173 | |||
174 | }; | ||
175 | |||
176 | |||
177 | /** | ||
178 | * Head of DLL of active blacklisting queries. | ||
179 | */ | ||
180 | static struct GST_BlacklistCheck *bc_head; | ||
181 | |||
182 | /** | ||
183 | * Tail of DLL of active blacklisting queries. | ||
184 | */ | ||
185 | static struct GST_BlacklistCheck *bc_tail; | ||
186 | |||
187 | /** | ||
188 | * Head of DLL of blacklisting clients. | ||
189 | */ | ||
190 | static struct Blacklisters *bl_head; | ||
191 | |||
192 | /** | ||
193 | * Tail of DLL of blacklisting clients. | ||
194 | */ | ||
195 | static struct Blacklisters *bl_tail; | ||
196 | |||
197 | /** | ||
198 | * Hashmap of blacklisted peers. Values are of type 'char *' (transport names), | ||
199 | * can be NULL if we have no static blacklist. | ||
200 | */ | ||
201 | static struct GNUNET_CONTAINER_MultiPeerMap *blacklist; | ||
202 | |||
203 | |||
204 | /** | ||
205 | * Perform next action in the blacklist check. | ||
206 | * | ||
207 | * @param cls the `struct BlacklistCheck*` | ||
208 | */ | ||
209 | static void | ||
210 | do_blacklist_check (void *cls); | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Called whenever a client is disconnected. Frees our | ||
215 | * resources associated with that client. | ||
216 | * | ||
217 | * @param cls closure (unused) | ||
218 | * @param client identification of the client | ||
219 | */ | ||
220 | static void | ||
221 | client_disconnect_notification (void *cls, | ||
222 | struct GNUNET_SERVER_Client *client) | ||
223 | { | ||
224 | struct Blacklisters *bl; | ||
225 | struct GST_BlacklistCheck *bc; | ||
226 | |||
227 | if (NULL == client) | ||
228 | return; | ||
229 | for (bl = bl_head; bl != NULL; bl = bl->next) | ||
230 | { | ||
231 | if (bl->client != client) | ||
232 | continue; | ||
233 | for (bc = bc_head; NULL != bc; bc = bc->next) | ||
234 | { | ||
235 | if (bc->bl_pos != bl) | ||
236 | continue; | ||
237 | bc->bl_pos = bl->next; | ||
238 | if (NULL != bc->th) | ||
239 | { | ||
240 | GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); | ||
241 | bc->th = NULL; | ||
242 | } | ||
243 | if (NULL == bc->task) | ||
244 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
245 | } | ||
246 | GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl); | ||
247 | GNUNET_SERVER_client_drop (bl->client); | ||
248 | GNUNET_free (bl); | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * Function to iterate over options in the blacklisting section for a peer. | ||
256 | * | ||
257 | * @param cls closure | ||
258 | * @param section name of the section | ||
259 | * @param option name of the option | ||
260 | * @param value value of the option | ||
261 | */ | ||
262 | static void | ||
263 | blacklist_cfg_iter (void *cls, | ||
264 | const char *section, | ||
265 | const char *option, | ||
266 | const char *value) | ||
267 | { | ||
268 | unsigned int *res = cls; | ||
269 | struct GNUNET_PeerIdentity peer; | ||
270 | char *plugs; | ||
271 | char *pos; | ||
272 | |||
273 | if (GNUNET_OK != | ||
274 | GNUNET_CRYPTO_eddsa_public_key_from_string (option, | ||
275 | strlen (option), | ||
276 | &peer.public_key)) | ||
277 | return; | ||
278 | |||
279 | if ((NULL == value) || (0 == strcmp(value, ""))) | ||
280 | { | ||
281 | /* Blacklist whole peer */ | ||
282 | GST_blacklist_add_peer (&peer, NULL); | ||
283 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
284 | _("Adding blacklisting entry for peer `%s'\n"), | ||
285 | GNUNET_i2s (&peer)); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | plugs = GNUNET_strdup (value); | ||
290 | for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) | ||
291 | { | ||
292 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
293 | _("Adding blacklisting entry for peer `%s':`%s'\n"), | ||
294 | GNUNET_i2s (&peer), pos); | ||
295 | GST_blacklist_add_peer (&peer, pos); | ||
296 | } | ||
297 | GNUNET_free (plugs); | ||
298 | } | ||
299 | (*res)++; | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Read blacklist configuration | ||
305 | * | ||
306 | * @param cfg the configuration handle | ||
307 | * @param my_id my peer identity | ||
308 | */ | ||
309 | static void | ||
310 | read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
311 | const struct GNUNET_PeerIdentity *my_id) | ||
312 | { | ||
313 | char cfg_sect[512]; | ||
314 | unsigned int res = 0; | ||
315 | |||
316 | GNUNET_snprintf (cfg_sect, | ||
317 | sizeof (cfg_sect), | ||
318 | "transport-blacklist-%s", | ||
319 | GNUNET_i2s_full (my_id)); | ||
320 | GNUNET_CONFIGURATION_iterate_section_values (cfg, | ||
321 | cfg_sect, | ||
322 | &blacklist_cfg_iter, | ||
323 | &res); | ||
324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
325 | "Loaded %u blacklisting entries from configuration\n", | ||
326 | res); | ||
327 | } | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Start blacklist subsystem. | ||
332 | * | ||
333 | * @param server server used to accept clients from | ||
334 | * @param cfg configuration handle | ||
335 | * @param my_id my peer id | ||
336 | */ | ||
337 | void | ||
338 | GST_blacklist_start (struct GNUNET_SERVER_Handle *server, | ||
339 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
340 | const struct GNUNET_PeerIdentity *my_id) | ||
341 | { | ||
342 | GNUNET_assert (NULL != cfg); | ||
343 | GNUNET_assert (NULL != my_id); | ||
344 | read_blacklist_configuration (cfg, my_id); | ||
345 | GNUNET_SERVER_disconnect_notify (server, | ||
346 | &client_disconnect_notification, | ||
347 | NULL); | ||
348 | } | ||
349 | |||
350 | |||
351 | /** | ||
352 | * Free the given entry in the blacklist. | ||
353 | * | ||
354 | * @param cls unused | ||
355 | * @param key host identity (unused) | ||
356 | * @param value the blacklist entry | ||
357 | * @return #GNUNET_OK (continue to iterate) | ||
358 | */ | ||
359 | static int | ||
360 | free_blacklist_entry (void *cls, | ||
361 | const struct GNUNET_PeerIdentity *key, | ||
362 | void *value) | ||
363 | { | ||
364 | char *be = value; | ||
365 | |||
366 | GNUNET_free_non_null (be); | ||
367 | return GNUNET_OK; | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Stop blacklist subsystem. | ||
373 | */ | ||
374 | void | ||
375 | GST_blacklist_stop () | ||
376 | { | ||
377 | if (NULL == blacklist) | ||
378 | return; | ||
379 | GNUNET_CONTAINER_multipeermap_iterate (blacklist, | ||
380 | &free_blacklist_entry, | ||
381 | NULL); | ||
382 | GNUNET_CONTAINER_multipeermap_destroy (blacklist); | ||
383 | blacklist = NULL; | ||
384 | } | ||
385 | |||
386 | |||
387 | /** | ||
388 | * Transmit blacklist query to the client. | ||
389 | * | ||
390 | * @param cls the `struct GST_BlacklistCheck` | ||
391 | * @param size number of bytes allowed | ||
392 | * @param buf where to copy the message | ||
393 | * @return number of bytes copied to @a buf | ||
394 | */ | ||
395 | static size_t | ||
396 | transmit_blacklist_message (void *cls, | ||
397 | size_t size, | ||
398 | void *buf) | ||
399 | { | ||
400 | struct GST_BlacklistCheck *bc = cls; | ||
401 | struct Blacklisters *bl; | ||
402 | struct BlacklistMessage bm; | ||
403 | |||
404 | bc->th = NULL; | ||
405 | if (0 == size) | ||
406 | { | ||
407 | GNUNET_assert (NULL == bc->task); | ||
408 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
409 | bc); | ||
410 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
411 | "Failed to send blacklist test for peer `%s' to client\n", | ||
412 | GNUNET_i2s (&bc->peer)); | ||
413 | return 0; | ||
414 | } | ||
415 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
416 | "Sending blacklist test for peer `%s' to client %p\n", | ||
417 | GNUNET_i2s (&bc->peer), | ||
418 | bc->bl_pos->client); | ||
419 | bl = bc->bl_pos; | ||
420 | bm.header.size = htons (sizeof (struct BlacklistMessage)); | ||
421 | bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); | ||
422 | bm.is_allowed = htonl (0); | ||
423 | bm.peer = bc->peer; | ||
424 | GNUNET_memcpy (buf, | ||
425 | &bm, | ||
426 | sizeof (bm)); | ||
427 | if (GNUNET_YES == bl->call_receive_done) | ||
428 | { | ||
429 | GNUNET_SERVER_receive_done (bl->client, | ||
430 | GNUNET_OK); | ||
431 | bl->call_receive_done = GNUNET_NO; | ||
432 | } | ||
433 | |||
434 | bl->waiting_for_reply = GNUNET_YES; | ||
435 | return sizeof (bm); | ||
436 | } | ||
437 | |||
438 | |||
439 | /** | ||
440 | * Perform next action in the blacklist check. | ||
441 | * | ||
442 | * @param cls the `struct GST_BlacklistCheck *` | ||
443 | */ | ||
444 | static void | ||
445 | do_blacklist_check (void *cls) | ||
446 | { | ||
447 | struct GST_BlacklistCheck *bc = cls; | ||
448 | struct Blacklisters *bl; | ||
449 | |||
450 | bc->task = NULL; | ||
451 | bl = bc->bl_pos; | ||
452 | if (NULL == bl) | ||
453 | { | ||
454 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
455 | "No other blacklist clients active, will allow neighbour `%s'\n", | ||
456 | GNUNET_i2s (&bc->peer)); | ||
457 | |||
458 | bc->cont (bc->cont_cls, | ||
459 | &bc->peer, | ||
460 | bc->address, | ||
461 | bc->session, | ||
462 | GNUNET_OK); | ||
463 | GST_blacklist_test_cancel (bc); | ||
464 | return; | ||
465 | } | ||
466 | if ( (NULL != bl->bc) || | ||
467 | (GNUNET_NO != bl->waiting_for_reply) ) | ||
468 | return; /* someone else busy with this client */ | ||
469 | bl->bc = bc; | ||
470 | bc->th = | ||
471 | GNUNET_SERVER_notify_transmit_ready (bl->client, | ||
472 | sizeof (struct BlacklistMessage), | ||
473 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
474 | &transmit_blacklist_message, | ||
475 | bc); | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Got the result about an existing connection from a new blacklister. | ||
481 | * Shutdown the neighbour if necessary. | ||
482 | * | ||
483 | * @param cls unused | ||
484 | * @param peer the neighbour that was investigated | ||
485 | * @param address address associated with the request | ||
486 | * @param session session associated with the request | ||
487 | * @param allowed #GNUNET_OK if we can keep it, | ||
488 | * #GNUNET_NO if we must shutdown the connection | ||
489 | */ | ||
490 | static void | ||
491 | confirm_or_drop_neighbour (void *cls, | ||
492 | const struct GNUNET_PeerIdentity *peer, | ||
493 | const struct GNUNET_HELLO_Address *address, | ||
494 | struct GNUNET_ATS_Session *session, | ||
495 | int allowed) | ||
496 | { | ||
497 | if (GNUNET_OK == allowed) | ||
498 | return; /* we're done */ | ||
499 | GNUNET_STATISTICS_update (GST_stats, | ||
500 | gettext_noop ("# disconnects due to blacklist"), | ||
501 | 1, | ||
502 | GNUNET_NO); | ||
503 | GST_neighbours_force_disconnect (peer); | ||
504 | } | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Closure for #test_connection_ok(). | ||
509 | */ | ||
510 | struct TestConnectionContext | ||
511 | { | ||
512 | /** | ||
513 | * Is this the first neighbour we're checking? | ||
514 | */ | ||
515 | int first; | ||
516 | |||
517 | /** | ||
518 | * Handle to the blacklisting client we need to ask. | ||
519 | */ | ||
520 | struct Blacklisters *bl; | ||
521 | }; | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Test if an existing connection is still acceptable given a new | ||
526 | * blacklisting client. | ||
527 | * | ||
528 | * @param cls the `struct TestConnectionContext *` | ||
529 | * @param peer identity of the peer | ||
530 | * @param address the address | ||
531 | * @param state current state this peer is in | ||
532 | * @param state_timeout timeout for the current state of the peer | ||
533 | * @param bandwidth_in bandwidth assigned inbound | ||
534 | * @param bandwidth_out bandwidth assigned outbound | ||
535 | */ | ||
536 | static void | ||
537 | test_connection_ok (void *cls, | ||
538 | const struct GNUNET_PeerIdentity *peer, | ||
539 | const struct GNUNET_HELLO_Address *address, | ||
540 | enum GNUNET_TRANSPORT_PeerState state, | ||
541 | struct GNUNET_TIME_Absolute state_timeout, | ||
542 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
543 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
544 | { | ||
545 | struct TestConnectionContext *tcc = cls; | ||
546 | struct GST_BlacklistCheck *bc; | ||
547 | |||
548 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
549 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
550 | bc_tail, | ||
551 | bc); | ||
552 | bc->peer = *peer; | ||
553 | bc->address = GNUNET_HELLO_address_copy (address); | ||
554 | bc->cont = &confirm_or_drop_neighbour; | ||
555 | bc->cont_cls = NULL; | ||
556 | bc->bl_pos = tcc->bl; | ||
557 | if (GNUNET_YES == tcc->first) | ||
558 | { | ||
559 | /* all would wait for the same client, no need to | ||
560 | * create more than just the first task right now */ | ||
561 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
562 | tcc->first = GNUNET_NO; | ||
563 | } | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * Initialize a blacklisting client. We got a blacklist-init | ||
569 | * message from this client, add him to the list of clients | ||
570 | * to query for blacklisting. | ||
571 | * | ||
572 | * @param cls unused | ||
573 | * @param client the client | ||
574 | * @param message the blacklist-init message that was sent | ||
575 | */ | ||
576 | void | ||
577 | GST_blacklist_handle_init (void *cls, | ||
578 | struct GNUNET_SERVER_Client *client, | ||
579 | const struct GNUNET_MessageHeader *message) | ||
580 | { | ||
581 | struct Blacklisters *bl; | ||
582 | struct TestConnectionContext tcc; | ||
583 | |||
584 | for (bl = bl_head; NULL != bl; bl = bl->next) | ||
585 | if (bl->client == client) | ||
586 | { | ||
587 | GNUNET_break (0); | ||
588 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | GNUNET_SERVER_client_mark_monitor (client); | ||
593 | bl = GNUNET_new (struct Blacklisters); | ||
594 | bl->client = client; | ||
595 | bl->call_receive_done = GNUNET_YES; | ||
596 | GNUNET_SERVER_client_keep (client); | ||
597 | GNUNET_CONTAINER_DLL_insert_after (bl_head, | ||
598 | bl_tail, | ||
599 | bl_tail, | ||
600 | bl); | ||
601 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
602 | "New blacklist client %p\n", | ||
603 | client); | ||
604 | |||
605 | /* confirm that all existing connections are OK! */ | ||
606 | tcc.bl = bl; | ||
607 | tcc.first = GNUNET_YES; | ||
608 | GST_neighbours_iterate (&test_connection_ok, &tcc); | ||
609 | } | ||
610 | |||
611 | |||
612 | /** | ||
613 | * A blacklisting client has sent us reply. Process it. | ||
614 | * | ||
615 | * @param cls unused | ||
616 | * @param client the client | ||
617 | * @param message the blacklist-init message that was sent | ||
618 | */ | ||
619 | void | ||
620 | GST_blacklist_handle_reply (void *cls, | ||
621 | struct GNUNET_SERVER_Client *client, | ||
622 | const struct GNUNET_MessageHeader *message) | ||
623 | { | ||
624 | const struct BlacklistMessage *msg = | ||
625 | (const struct BlacklistMessage *) message; | ||
626 | struct Blacklisters *bl; | ||
627 | struct GST_BlacklistCheck *bc; | ||
628 | |||
629 | bl = bl_head; | ||
630 | while ((bl != NULL) && (bl->client != client)) | ||
631 | bl = bl->next; | ||
632 | if (NULL == bl) | ||
633 | { | ||
634 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
635 | "Blacklist client disconnected\n"); | ||
636 | GNUNET_SERVER_receive_done (client, | ||
637 | GNUNET_SYSERR); | ||
638 | return; | ||
639 | } | ||
640 | |||
641 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
642 | "Blacklist client %p sent reply for `%s'\n", | ||
643 | client, | ||
644 | GNUNET_i2s (&msg->peer)); | ||
645 | |||
646 | bc = bl->bc; | ||
647 | bl->bc = NULL; | ||
648 | bl->waiting_for_reply = GNUNET_NO; | ||
649 | bl->call_receive_done = GNUNET_YES; /* Remember to call receive_done */ | ||
650 | if (NULL != bc) | ||
651 | { | ||
652 | /* only run this if the blacklist check has not been | ||
653 | * cancelled in the meantime... */ | ||
654 | GNUNET_assert (bc->bl_pos == bl); | ||
655 | if (ntohl (msg->is_allowed) == GNUNET_SYSERR) | ||
656 | { | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
658 | "Blacklist check failed, peer not allowed\n"); | ||
659 | /* For the duration of the continuation, make the ongoing | ||
660 | check invisible (to avoid double-cancellation); then | ||
661 | add it back again so we can re-use GST_blacklist_test_cancel() */ | ||
662 | GNUNET_CONTAINER_DLL_remove (bc_head, | ||
663 | bc_tail, | ||
664 | bc); | ||
665 | bc->cont (bc->cont_cls, | ||
666 | &bc->peer, | ||
667 | bc->address, | ||
668 | bc->session, | ||
669 | GNUNET_NO); | ||
670 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
671 | bc_tail, | ||
672 | bc); | ||
673 | GST_blacklist_test_cancel (bc); | ||
674 | GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); | ||
675 | bl->call_receive_done = GNUNET_NO; | ||
676 | return; | ||
677 | } | ||
678 | else | ||
679 | { | ||
680 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
681 | "Blacklist check succeeded, continuing with checks\n"); | ||
682 | GNUNET_SERVER_receive_done (bl->client, | ||
683 | GNUNET_OK); | ||
684 | bl->call_receive_done = GNUNET_NO; | ||
685 | bc->bl_pos = bl->next; | ||
686 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
687 | bc); | ||
688 | } | ||
689 | } | ||
690 | /* check if any other blacklist checks are waiting for this blacklister */ | ||
691 | for (bc = bc_head; bc != NULL; bc = bc->next) | ||
692 | if ((bc->bl_pos == bl) && (NULL == bc->task)) | ||
693 | { | ||
694 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
695 | bc); | ||
696 | break; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | |||
701 | /** | ||
702 | * Add the given peer to the blacklist (for the given transport). | ||
703 | * | ||
704 | * @param peer peer to blacklist | ||
705 | * @param transport_name transport to blacklist for this peer, NULL for all | ||
706 | */ | ||
707 | void | ||
708 | GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, | ||
709 | const char *transport_name) | ||
710 | { | ||
711 | char *transport = NULL; | ||
712 | |||
713 | if (NULL != transport_name) | ||
714 | { | ||
715 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
716 | "Adding peer `%s' with plugin `%s' to blacklist\n", | ||
717 | GNUNET_i2s (peer), transport_name); | ||
718 | transport = GNUNET_strdup (transport_name); | ||
719 | } | ||
720 | else | ||
721 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
722 | "Adding peer `%s' with all plugins to blacklist\n", | ||
723 | GNUNET_i2s (peer)); | ||
724 | if (NULL == blacklist) | ||
725 | blacklist = | ||
726 | GNUNET_CONTAINER_multipeermap_create (TRANSPORT_BLACKLIST_HT_SIZE, | ||
727 | GNUNET_NO); | ||
728 | |||
729 | GNUNET_CONTAINER_multipeermap_put (blacklist, peer, | ||
730 | transport, | ||
731 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
732 | } | ||
733 | |||
734 | |||
735 | /** | ||
736 | * Abort blacklist if @a address and @a session match. | ||
737 | * | ||
738 | * @param address address used to abort matching checks | ||
739 | * @param session session used to abort matching checks | ||
740 | */ | ||
741 | void | ||
742 | GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address, | ||
743 | struct GNUNET_ATS_Session *session) | ||
744 | { | ||
745 | struct GST_BlacklistCheck *bc; | ||
746 | struct GST_BlacklistCheck *n; | ||
747 | |||
748 | n = bc_head; | ||
749 | while (NULL != (bc = n)) | ||
750 | { | ||
751 | n = bc->next; | ||
752 | if ( (bc->session == session) && | ||
753 | (0 == GNUNET_HELLO_address_cmp (bc->address, | ||
754 | address)) ) | ||
755 | { | ||
756 | bc->cont (bc->cont_cls, | ||
757 | &bc->peer, | ||
758 | bc->address, | ||
759 | bc->session, | ||
760 | GNUNET_SYSERR); | ||
761 | GST_blacklist_test_cancel (bc); | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | |||
767 | /** | ||
768 | * Test if the given blacklist entry matches. If so, | ||
769 | * abort the iteration. | ||
770 | * | ||
771 | * @param cls the transport name to match (const char*) | ||
772 | * @param key the key (unused) | ||
773 | * @param value the 'char *' (name of a blacklisted transport) | ||
774 | * @return #GNUNET_OK if the entry does not match, #GNUNET_NO if it matches | ||
775 | */ | ||
776 | static int | ||
777 | test_blacklisted (void *cls, | ||
778 | const struct GNUNET_PeerIdentity *key, | ||
779 | void *value) | ||
780 | { | ||
781 | const char *transport_name = cls; | ||
782 | char *be = value; | ||
783 | |||
784 | /* Blacklist entry be: | ||
785 | * (NULL == be): peer is blacklisted with all plugins | ||
786 | * (NULL != be): peer is blacklisted for a specific plugin | ||
787 | * | ||
788 | * If (NULL != transport_name) we look for a transport specific entry: | ||
789 | * if (transport_name == be) forbidden | ||
790 | * | ||
791 | */ | ||
792 | |||
793 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
794 | "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n", | ||
795 | GNUNET_i2s (key), | ||
796 | (NULL == transport_name) ? "unspecified" : transport_name, | ||
797 | (NULL == be) ? "all plugins" : be); | ||
798 | /* all plugins for this peer were blacklisted: disallow */ | ||
799 | if (NULL == value) | ||
800 | return GNUNET_NO; | ||
801 | |||
802 | /* blacklist check for specific transport */ | ||
803 | if ((NULL != transport_name) && (NULL != value)) | ||
804 | { | ||
805 | if (0 == strcmp (transport_name, | ||
806 | be)) | ||
807 | return GNUNET_NO; /* plugin is blacklisted! */ | ||
808 | } | ||
809 | return GNUNET_OK; | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Test if a peer/transport combination is blacklisted. | ||
815 | * | ||
816 | * @param peer the identity of the peer to test | ||
817 | * @param transport_name name of the transport to test, never NULL | ||
818 | * @param cont function to call with result | ||
819 | * @param cont_cls closure for @a cont | ||
820 | * @param address address to pass back to @a cont, can be NULL | ||
821 | * @param session session to pass back to @a cont, can be NULL | ||
822 | * @return handle to the blacklist check, NULL if the decision | ||
823 | * was made instantly and @a cont was already called | ||
824 | */ | ||
825 | struct GST_BlacklistCheck * | ||
826 | GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, | ||
827 | const char *transport_name, | ||
828 | GST_BlacklistTestContinuation cont, | ||
829 | void *cont_cls, | ||
830 | const struct GNUNET_HELLO_Address *address, | ||
831 | struct GNUNET_ATS_Session *session) | ||
832 | { | ||
833 | struct GST_BlacklistCheck *bc; | ||
834 | |||
835 | GNUNET_assert (NULL != peer); | ||
836 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
837 | "Blacklist check for peer `%s':%s\n", | ||
838 | GNUNET_i2s (peer), | ||
839 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
840 | |||
841 | /* Check local blacklist by iterating over hashmap | ||
842 | * If iteration is aborted, we found a matching blacklist entry */ | ||
843 | if ((NULL != blacklist) && | ||
844 | (GNUNET_SYSERR == | ||
845 | GNUNET_CONTAINER_multipeermap_get_multiple (blacklist, peer, | ||
846 | &test_blacklisted, | ||
847 | (void *) transport_name))) | ||
848 | { | ||
849 | /* Disallowed by config, disapprove instantly */ | ||
850 | GNUNET_STATISTICS_update (GST_stats, | ||
851 | gettext_noop ("# disconnects due to blacklist"), | ||
852 | 1, | ||
853 | GNUNET_NO); | ||
854 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
855 | _("Disallowing connection to peer `%s' on transport %s\n"), | ||
856 | GNUNET_i2s (peer), | ||
857 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
858 | if (NULL != cont) | ||
859 | cont (cont_cls, | ||
860 | peer, | ||
861 | address, | ||
862 | session, | ||
863 | GNUNET_NO); | ||
864 | return NULL; | ||
865 | } | ||
866 | |||
867 | if (NULL == bl_head) | ||
868 | { | ||
869 | /* no blacklist clients, approve instantly */ | ||
870 | if (NULL != cont) | ||
871 | cont (cont_cls, | ||
872 | peer, | ||
873 | address, | ||
874 | session, | ||
875 | GNUNET_OK); | ||
876 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
877 | "Allowing connection to peer `%s' %s\n", | ||
878 | GNUNET_i2s (peer), | ||
879 | (NULL != transport_name) ? transport_name : ""); | ||
880 | return NULL; | ||
881 | } | ||
882 | |||
883 | /* need to query blacklist clients */ | ||
884 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
885 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
886 | bc_tail, | ||
887 | bc); | ||
888 | bc->peer = *peer; | ||
889 | bc->address = GNUNET_HELLO_address_copy (address); | ||
890 | bc->session = session; | ||
891 | bc->cont = cont; | ||
892 | bc->cont_cls = cont_cls; | ||
893 | bc->bl_pos = bl_head; | ||
894 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
895 | return bc; | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Cancel a blacklist check. | ||
901 | * | ||
902 | * @param bc check to cancel | ||
903 | */ | ||
904 | void | ||
905 | GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc) | ||
906 | { | ||
907 | GNUNET_CONTAINER_DLL_remove (bc_head, | ||
908 | bc_tail, | ||
909 | bc); | ||
910 | if (NULL != bc->bl_pos) | ||
911 | { | ||
912 | if (bc->bl_pos->bc == bc) | ||
913 | { | ||
914 | /* we're at the head of the queue, remove us! */ | ||
915 | bc->bl_pos->bc = NULL; | ||
916 | } | ||
917 | } | ||
918 | if (NULL != bc->task) | ||
919 | { | ||
920 | GNUNET_SCHEDULER_cancel (bc->task); | ||
921 | bc->task = NULL; | ||
922 | } | ||
923 | if (NULL != bc->th) | ||
924 | { | ||
925 | GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); | ||
926 | bc->th = NULL; | ||
927 | } | ||
928 | GNUNET_free_non_null (bc->address); | ||
929 | GNUNET_free (bc); | ||
930 | } | ||
931 | |||
932 | |||
933 | /* end of file gnunet-service-transport_blacklist.c */ | ||