aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-12-29 21:49:53 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-12-29 21:49:53 +0000
commite069ce6318baababf6792335c1277a4b0d856cf2 (patch)
tree08f601703e1aa844216b4c52bb4b219d10eceb5f /src/testbed
parent2b27fe35e5674c1bb7e077cd9c294c6eb0ff425e (diff)
downloadgnunet-e069ce6318baababf6792335c1277a4b0d856cf2.tar.gz
gnunet-e069ce6318baababf6792335c1277a4b0d856cf2.zip
- testbed underlay daemon
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/Makefile.am16
-rw-r--r--src/testbed/gnunet-daemon-testbed-underlay.c490
2 files changed, 505 insertions, 1 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 6259f4404..015bd85b0 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -16,11 +16,16 @@ pkgcfgdir= $(pkgdatadir)/config.d/
16pkgcfg_DATA = \ 16pkgcfg_DATA = \
17 testbed.conf 17 testbed.conf
18 18
19if HAVE_SQLITE
20 underlay_daemon = gnunet-daemon-testbed-underlay
21endif
22
19libexec_PROGRAMS = \ 23libexec_PROGRAMS = \
20 gnunet-service-testbed \ 24 gnunet-service-testbed \
21 gnunet-helper-testbed \ 25 gnunet-helper-testbed \
22 gnunet-service-testbed-logger \ 26 gnunet-service-testbed-logger \
23 gnunet-daemon-testbed-blacklist 27 gnunet-daemon-testbed-blacklist \
28 $(underlay_daemon)
24 29
25bin_PROGRAMS = \ 30bin_PROGRAMS = \
26 gnunet-testbed-profiler 31 gnunet-testbed-profiler
@@ -83,6 +88,15 @@ gnunet_daemon_testbed_blacklist_DEPENDENCIES = \
83 $(top_builddir)/src/transport/libgnunettransport.la \ 88 $(top_builddir)/src/transport/libgnunettransport.la \
84 $(top_builddir)/src/util/libgnunetutil.la 89 $(top_builddir)/src/util/libgnunetutil.la
85 90
91gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c
92gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \
93 $(top_builddir)/src/transport/libgnunettransport.la \
94 $(top_builddir)/src/util/libgnunetutil.la \
95 $(LTLIBINTL) -lsqlite3
96gnunet_daemon_testbed_underlay_DEPENDENCIES = \
97 $(top_builddir)/src/transport/libgnunettransport.la \
98 $(top_builddir)/src/util/libgnunetutil.la
99
86lib_LTLIBRARIES = \ 100lib_LTLIBRARIES = \
87 libgnunettestbed.la \ 101 libgnunettestbed.la \
88 libgnunettestbedlogger.la 102 libgnunettestbedlogger.la
diff --git a/src/testbed/gnunet-daemon-testbed-underlay.c b/src/testbed/gnunet-daemon-testbed-underlay.c
new file mode 100644
index 000000000..9fe59e3fb
--- /dev/null
+++ b/src/testbed/gnunet-daemon-testbed-underlay.c
@@ -0,0 +1,490 @@
1/*
2 This file is part of GNUnet
3 (C) 2008--2013 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 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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21
22/**
23 * @file testbed/gnunet-daemon-testbed-blacklist.c
24 * @brief daemon to restrict incoming connections from other peers at the
25 * transport layer of a peer
26 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_transport_service.h"
32#include "gnunet_testing_lib.h"
33#include <sqlite3.h>
34
35/**
36 * Logging shorthand
37 */
38#define LOG(type,...) \
39 GNUNET_log (type, __VA_ARGS__)
40
41/**
42 * Debug logging shorthand
43 */
44#define DEBUG(...) \
45 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
46
47
48#define LOG_SQLITE_ERROR(ret) \
49 LOG (GNUNET_ERROR_TYPE_ERROR, "sqlite error: %s", sqlite3_errstr (ret))
50
51
52/**
53 * Allow access from the peers read from the whitelist
54 */
55#define ACCESS_ALLOW 1
56
57/**
58 * Deny access from the peers read from the blacklist
59 */
60#define ACCESS_DENY 0
61
62/**
63 * The map to store the peer identities to allow/deny
64 */
65static struct GNUNET_CONTAINER_MultiPeerMap *map;
66
67
68/**
69 * The map to store the peer identities to allow/deny
70 */
71static struct GNUNET_CONTAINER_MultiPeerMap *blacklist_map;
72
73/**
74 * The database connection
75 */
76static struct sqlite3 *db;
77
78/**
79 * The array of peer identities we read from whitelist/blacklist
80 */
81static struct GNUNET_PeerIdentity *ilist;
82
83/**
84 * The blacklist handle we obtain from transport when we register ourselves for
85 * access control
86 */
87struct GNUNET_TRANSPORT_Blacklist *bh;
88
89/**
90 * The peer ID map
91 */
92static struct GNUNET_DISK_MapHandle *idmap;
93
94/**
95 * The hostkeys data
96 */
97static struct GNUNET_PeerIdentity *hostkeys;
98
99/**
100 * The number of hostkeys in the hostkeys array
101 */
102static unsigned int num_hostkeys;
103
104/**
105 * Task for shutdown
106 */
107static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
108
109/**
110 * Are we allowing or denying access from peers
111 */
112static int mode;
113
114
115/**
116 * @ingroup hashmap
117 * Iterator over hash map entries.
118 *
119 * @param cls closure
120 * @param key current key code
121 * @param value value in the hash map
122 * @return #GNUNET_YES if we should continue to
123 * iterate,
124 * #GNUNET_NO if not.
125 */
126static int
127iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
128{
129 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key,
130 value));
131 return GNUNET_YES;
132}
133
134
135/**
136 * Cleaup and destroy the map
137 */
138static void
139cleanup_map ()
140{
141 if (NULL != map)
142 {
143 GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map,
144 &iterator,
145 NULL));
146 GNUNET_CONTAINER_multipeermap_destroy (map);
147 map = NULL;
148 }
149}
150
151
152/**
153 * Shutdown task to cleanup our resources and exit.
154 *
155 * @param cls NULL
156 * @param tc scheduler task context
157 */
158static void
159do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
160{
161 cleanup_map ();
162 if (NULL != bh)
163 GNUNET_TRANSPORT_blacklist_cancel (bh);
164}
165
166
167/**
168 * Function that decides if a connection is acceptable or not.
169 *
170 * @param cls closure
171 * @param pid peer to approve or disapproave
172 * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not
173 */
174static int
175check_access (void *cls, const struct GNUNET_PeerIdentity * pid)
176{
177 int contains;
178
179 if (NULL != map)
180 contains = GNUNET_CONTAINER_multipeermap_contains (map, pid);
181 else
182 contains = GNUNET_NO;
183 if (ACCESS_DENY == mode)
184 return (contains) ? GNUNET_SYSERR : GNUNET_OK;
185 return (contains) ? GNUNET_OK : GNUNET_SYSERR;
186}
187
188
189/**
190 * Setup the access control by reading the given file containing peer identities
191 * and then establishing blacklist handler with the peer's transport service
192 *
193 * @param fname the filename to read the list of peer identities
194 * @param cfg the configuration for connecting to the peer's transport service
195 */
196static void
197setup_ac (const char *fname, const struct GNUNET_CONFIGURATION_Handle *cfg)
198{
199 uint64_t fsize;
200 unsigned int npeers;
201 unsigned int cnt;
202
203 GNUNET_assert (GNUNET_OK != GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO,
204 GNUNET_YES));
205 if (0 != (fsize % sizeof (struct GNUNET_PeerIdentity)))
206 {
207 GNUNET_break (0);
208 return;
209 }
210 npeers = fsize / sizeof (struct GNUNET_PeerIdentity);
211 if (0 != npeers)
212 {
213 map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES);
214 ilist = GNUNET_malloc_large (fsize);
215 GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize));
216 }
217 for (cnt = 0; cnt < npeers; cnt++)
218 {
219 if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt],
220 &ilist[cnt],
221 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
222 {
223 cleanup_map ();
224 GNUNET_free (ilist);
225 return;
226 }
227 }
228 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
229 &do_shutdown, NULL);
230 bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, NULL);
231}
232
233
234/**
235 * Function to blacklist a peer
236 *
237 * @param offset the offset where to find the peer's hostkey in the array of hostkeys
238 */
239static void
240blacklist_peer (unsigned int offset)
241{
242 struct GNUNET_CRYPTO_EddsaPrivateKey private_key;
243 struct GNUNET_PeerIdentity id;
244
245 (void) memcpy (&private_key, &hostkeys[offset], sizeof (private_key));
246 GNUNET_CRYPTO_eddsa_key_get_public (&private_key, &id.public_key);
247 GNUNET_break (GNUNET_OK ==
248 GNUNET_CONTAINER_multipeermap_put (map, &id, &id,
249 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
250
251}
252
253/**
254 * Blacklist peer
255 */
256struct ListRow
257{
258 /**
259 * Next ptr
260 */
261 struct ListRow *next;
262
263 /**
264 * The offset where to find the hostkey for the peer
265 */
266 unsigned int id;
267};
268
269
270/**
271 * Function to add a peer to the blacklist
272 *
273 * @param head the head of the list
274 * @param id the id of the peer to add
275 */
276static void
277listrow_add (struct ListRow *head, unsigned int id)
278{
279 struct ListRow *bp;
280
281 bp = GNUNET_new (struct ListRow);
282 bp->id = id;
283 bp->next = head;
284 head = bp;
285}
286
287
288/**
289 * Add peers in the blacklist to the blacklist map
290 */
291static int
292map_populate (struct ListRow *head,
293 struct GNUNET_CONTAINER_MultiPeerMap *map,
294 const struct GNUNET_PeerIdentity *hostkeys)
295{
296 struct ListRow *row;
297 int ret;
298
299 while (NULL != (row = head))
300 {
301 if (head->id >= num_hostkeys)
302 {
303 LOG (GNUNET_ERROR_TYPE_WARNING, "Hostkey index %u out of max range %u\n",
304 row->id, num_hostkeys);
305 }
306 head = row->next;
307 ret = GNUNET_CONTAINER_multipeermap_put (blacklist_map, &hostkeys[row->id],
308 (void *) &hostkeys[row->id],
309 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
310 if (GNUNET_OK != ret)
311 return GNUNET_SYSERR;
312 }
313 return GNUNET_OK;
314}
315
316
317/**
318 * Function to load keys
319 */
320static int
321load_keys (const struct GNUNET_CONFIGURATION_Handle *c)
322{
323 char *data_dir;
324 char *idfile;
325 struct GNUNET_DISK_FileHandle *fd;
326 uint64_t fsize;
327
328 data_dir = NULL;
329 idfile = NULL;
330 fd = NULL;
331 fsize = 0;
332 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
333 GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir);
334 GNUNET_free (data_dir);
335 data_dir = NULL;
336 if (GNUNET_OK !=
337 GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES))
338 {
339 GNUNET_free (idfile);
340 return GNUNET_SYSERR;
341 }
342 if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE))
343 {
344 LOG (GNUNET_ERROR_TYPE_ERROR,
345 _("Incorrect hostkey file format: %s\n"), idfile);
346 GNUNET_free (idfile);
347 return GNUNET_SYSERR;
348 }
349 fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ,
350 GNUNET_DISK_PERM_NONE);
351 if (NULL == fd)
352 {
353 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", idfile);
354 GNUNET_free (idfile);
355 return GNUNET_SYSERR;
356 }
357 GNUNET_free (idfile);
358 idfile = NULL;
359 hostkeys = (struct GNUNET_PeerIdentity *)
360 GNUNET_DISK_file_map (fd, &idmap, GNUNET_DISK_MAP_TYPE_READ, fsize);
361 if (NULL == hostkeys)
362 num_hostkeys = fsize / GNUNET_TESTING_HOSTKEYFILESIZE;
363 return GNUNET_OK;
364}
365
366
367static int
368db_read_blacklist (sqlite3 *dbfile, unsigned int pid, struct ListRow **blacklist_rows)
369{
370 static const char *query_bl = "SELECT (id, oid) FROM blacklist WHERE (id == ?);";
371 static struct sqlite3_stmt *stmt_bl;
372 int nrows;
373 int peer_id;
374 int ret;
375
376 if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_bl, -1, &stmt_bl, NULL)))
377 {
378 LOG_SQLITE_ERROR (ret);
379 return GNUNET_SYSERR;
380 }
381 if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_bl, 1, pid)))
382 {
383 LOG_SQLITE_ERROR (ret);
384 sqlite3_finalize (stmt_bl);
385 return GNUNET_SYSERR;
386 }
387 nrows = 0;
388 do
389 {
390 ret = sqlite3_step (stmt_bl);
391 if (SQLITE_ROW != ret)
392 break;
393 peer_id = sqlite3_column_int (stmt_bl, 1);
394 listrow_add (*blacklist_rows, peer_id);
395 nrows++;
396 } while (1);
397 sqlite3_finalize (stmt_bl);
398 stmt_bl = NULL;
399 return nrows;
400}
401
402
403/**
404 * Main function that will be run.
405 *
406 * @param cls closure
407 * @param args remaining command-line arguments
408 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
409 * @param c configuration
410 */
411static void
412run (void *cls, char *const *args, const char *cfgfile,
413 const struct GNUNET_CONFIGURATION_Handle *c)
414{
415 char *dbfile;
416 struct ListRow *blacklist_rows;
417 unsigned long long pid;
418 unsigned int nrows;
419 int ret;
420
421 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "TESTBED",
422 "PEERID", &pid))
423 {
424 GNUNET_break (0);
425 return;
426 }
427 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED",
428 "UNDERLAY_DB",
429 &dbfile))
430 {
431 GNUNET_break (0);
432 return;
433 }
434 if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL)))
435 {
436 LOG_SQLITE_ERROR (ret);
437 GNUNET_free (dbfile);
438 return;
439 }
440 DEBUG ("Opened database %s\n", dbfile);
441 GNUNET_free (dbfile);
442 dbfile = NULL;
443 blacklist_rows = NULL;
444 nrows = db_read_blacklist (db, pid, &blacklist_rows);
445 if (-1 == nrows)
446 goto close_db;
447 if (nrows > 0)
448 {
449 blacklist_map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_YES);
450 if (GNUNET_OK != load_keys (c))
451 {
452 goto close_db;
453 }
454 }
455 /* process whitelist */
456 GNUNET_break (0); /* TODO */
457
458 close_db:
459 GNUNET_break (GNUNET_OK == sqlite3_close (db));
460 return;
461}
462
463
464/**
465 * The main function.
466 *
467 * @param argc number of arguments from the command line
468 * @param argv command line arguments
469 * @return 0 ok, 1 on error
470 */
471int
472main (int argc, char *const *argv)
473{
474 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
475 GNUNET_GETOPT_OPTION_END
476 };
477 int ret;
478
479 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
480 return 2;
481 (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000);
482 ret =
483 (GNUNET_OK ==
484 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-testbed-underlay",
485 _
486 ("Daemon to restrict underlay network in testbed deployments"),
487 options, &run, NULL)) ? 0 : 1;
488 GNUNET_free ((void*) argv);
489 return ret;
490}