d149443626df74e309a236e82729db21dcb4c3bb
[oweals/gnunet.git] / src / testbed / gnunet-daemon-testbed-blacklist.c
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
33
34 /**
35  * Logging shorthand
36  */
37 #define LOG(type,...)                           \
38   GNUNET_log (type, __VA_ARGS__)
39
40 /**
41  * Debug logging shorthand
42  */
43 #define DEBUG(...)                              \
44   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
45
46 /**
47  * Allow access from the peers read from the whitelist
48  */
49 #define ACCESS_ALLOW 1
50
51 /**
52  * Deny access from the peers read from the blacklist
53  */
54 #define ACCESS_DENY 0
55
56 /**
57  * The map to store the peer identities to allow/deny
58  */
59 static struct GNUNET_CONTAINER_MultiPeerMap *map;
60
61 /**
62  * The array of peer identities we read from whitelist/blacklist
63  */
64 static struct GNUNET_PeerIdentity *ilist;
65
66 /**
67  * The blacklist handle we obtain from transport when we register ourselves for
68  * access control
69  */
70 struct GNUNET_TRANSPORT_Blacklist *bh;
71
72 /**
73  * Task for shutdown
74  */
75 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
76
77 /**
78  * Are we allowing or denying access from peers
79  */
80 static int mode;
81
82
83 /**
84  * @ingroup hashmap
85  * Iterator over hash map entries.
86  *
87  * @param cls closure
88  * @param key current key code
89  * @param value value in the hash map
90  * @return #GNUNET_YES if we should continue to
91  *         iterate,
92  *         #GNUNET_NO if not.
93  */
94 static int
95 iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
96 {
97   GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key,
98                                                                      value));
99   return GNUNET_YES;
100 }
101
102
103 /**
104  * Cleaup and destroy the map
105  */
106 static void
107 cleanup_map ()
108 {
109   if (NULL != map)
110   {
111     GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map,
112                                                                            &iterator,
113                                                                            NULL));
114     GNUNET_CONTAINER_multipeermap_destroy (map);
115     map = NULL;
116   }
117 }
118
119
120 /**
121  * Shutdown task to cleanup our resources and exit.
122  *
123  * @param cls NULL
124  * @param tc scheduler task context
125  */
126 static void
127 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
128 {
129   cleanup_map ();
130   if (NULL != bh)
131     GNUNET_TRANSPORT_blacklist_cancel (bh);
132 }
133
134
135 /**
136  * Function that decides if a connection is acceptable or not.
137  *
138  * @param cls closure
139  * @param pid peer to approve or disapproave
140  * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not
141  */
142 static int
143 check_access (void *cls, const struct GNUNET_PeerIdentity * pid)
144 {
145   int contains;
146  
147   if (NULL != map)
148     contains = GNUNET_CONTAINER_multipeermap_contains (map, pid);
149   else
150     contains = GNUNET_NO;
151   if (ACCESS_DENY == mode)
152     return (contains) ? GNUNET_SYSERR : GNUNET_OK;
153   return (contains) ? GNUNET_OK : GNUNET_SYSERR;
154 }
155
156
157 /**
158  * Setup the access control by reading the given file containing peer identities
159  * and then establishing blacklist handler with the peer's transport service
160  *
161  * @param fname the filename to read the list of peer identities
162  * @param cfg the configuration for connecting to the peer's transport service
163  */
164 static void
165 setup_ac (const char *fname, const struct GNUNET_CONFIGURATION_Handle *cfg)
166 {
167   uint64_t fsize;
168   unsigned int npeers;
169   unsigned int cnt;
170   
171   GNUNET_assert (GNUNET_OK != GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO,
172                                                      GNUNET_YES));
173   if (0 != (fsize % sizeof (struct GNUNET_PeerIdentity)))
174   {
175     GNUNET_break (0);
176     return;
177   }
178   npeers = fsize / sizeof (struct GNUNET_PeerIdentity);
179   if (0 != npeers)
180   {
181     map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES);
182     ilist = GNUNET_malloc_large (fsize);
183     GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize));
184   }
185   for (cnt = 0; cnt < npeers; cnt++)
186   {
187     if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt],
188                                                             &ilist[cnt],
189                                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
190     {
191       cleanup_map ();
192       GNUNET_free (ilist);
193       return;
194     }
195   }
196   shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
197                                                 &do_shutdown, NULL);
198   bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, NULL);
199 }
200
201
202 /**
203  * Main function that will be run.
204  *
205  * @param cls closure
206  * @param args remaining command-line arguments
207  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
208  * @param c configuration
209  */
210 static void
211 run (void *cls, char *const *args, const char *cfgfile,
212      const struct GNUNET_CONFIGURATION_Handle *c)
213 {
214   char *shome;
215   char fname[PATH_MAX];
216
217   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "PATHS",
218                                                           "SERVICEHOME",
219                                                           &shome))
220   {
221     GNUNET_break (0);
222     return;
223   }
224   GNUNET_assert (0 < GNUNET_snprintf (fname, PATH_MAX, "%s/whitelist", shome));
225   if (GNUNET_YES == GNUNET_DISK_file_test (fname))
226   {
227     mode = ACCESS_ALLOW;
228     setup_ac (fname, c);
229     GNUNET_free (shome);
230     return;
231   }
232   GNUNET_assert (0 < GNUNET_snprintf (fname, PATH_MAX, "%s/blacklist", shome));
233   if (GNUNET_YES == GNUNET_DISK_file_test (fname))
234   {
235     mode = ACCESS_DENY;
236     setup_ac (shome, c);
237   }
238   GNUNET_free (shome);
239   return;
240 }
241
242
243 /**
244  * The main function.
245  *
246  * @param argc number of arguments from the command line
247  * @param argv command line arguments
248  * @return 0 ok, 1 on error
249  */
250 int
251 main (int argc, char *const *argv)
252 {
253   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
254     GNUNET_GETOPT_OPTION_END
255   };
256   int ret;
257
258   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
259     return 2;
260   ret =
261       (GNUNET_OK ==
262        GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-testbed-blacklist",
263                            _
264                            ("Daemon to restrict incoming transport layer connections during testbed deployments"),
265                            options, &run, NULL)) ? 0 : 1;
266   GNUNET_free ((void*) argv);
267   return ret;
268 }