145726e143b2390114bb496f04f20af555ad6f8d
[oweals/gnunet.git] / src / revocation / test_revocation.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2009, 2013, 2016 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14   
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file revocation/test_revocation.c
20  * @brief base testcase for revocation exchange
21  * @author Matthias Wachs
22  * @author Christian Grothoff
23  */
24 #include "platform.h"
25 #include "gnunet_core_service.h"
26 #include "gnunet_identity_service.h"
27 #include "gnunet_revocation_service.h"
28 #include "gnunet_testbed_service.h"
29
30 #define NUM_TEST_PEERS 2
31
32 struct TestPeer
33 {
34   struct GNUNET_TESTBED_Peer *p;
35   struct GNUNET_TESTBED_Operation *identity_op;
36   struct GNUNET_TESTBED_Operation *core_op;
37   struct GNUNET_IDENTITY_Handle *idh;
38   const struct GNUNET_CONFIGURATION_Handle *cfg;
39   const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
40   struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
41   struct GNUNET_CRYPTO_EcdsaSignature sig;
42   struct GNUNET_IDENTITY_Operation *create_id_op;
43   struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
44   struct GNUNET_REVOCATION_Handle *revok_handle;
45   struct GNUNET_CORE_Handle *ch;
46   uint64_t pow;
47 };
48
49 static struct TestPeer testpeers[2];
50
51 /**
52  * Return value from main, set to 0 on success.
53  */
54 static int ok;
55
56
57 static void
58 do_shutdown (void *cls)
59 {
60   for (unsigned int c = 0; c < NUM_TEST_PEERS; c++)
61   {
62     if (NULL != testpeers[c].create_id_op)
63     {
64       GNUNET_IDENTITY_cancel (testpeers[c].create_id_op);
65       testpeers[c].create_id_op = NULL;
66     }
67     if (NULL != testpeers[c].ego_lookup)
68     {
69       GNUNET_IDENTITY_ego_lookup_cancel (testpeers[c].ego_lookup);
70       testpeers[c].ego_lookup = NULL;
71     }
72     if (NULL != testpeers[c].revok_handle)
73     {
74       GNUNET_REVOCATION_revoke_cancel (testpeers[c].revok_handle);
75       testpeers[c].revok_handle = NULL;
76     }
77     if (NULL != testpeers[c].identity_op)
78     {
79       GNUNET_TESTBED_operation_done (testpeers[c].identity_op);
80       testpeers[c].identity_op = NULL;
81     }
82     if (NULL != testpeers[c].core_op)
83     {
84       GNUNET_TESTBED_operation_done (testpeers[c].core_op);
85       testpeers[c].core_op = NULL;
86     }
87   }
88 }
89
90
91 static void
92 check_revocation (void *cls);
93
94
95 static void
96 revocation_remote_cb (void *cls,
97                       int is_valid)
98 {
99   static int repeat = 0;
100
101   if (GNUNET_NO == is_valid)
102   {
103     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
104                 "Local revocation successful\n");
105     ok = 0;
106     GNUNET_SCHEDULER_shutdown ();
107     return;
108   }
109   if (repeat < 10)
110   {
111     repeat++;
112     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
113                                   &check_revocation,
114                                   NULL);
115     return;
116   }
117   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118               "Flooding of revocation failed\n");
119   ok = 2;
120   GNUNET_SCHEDULER_shutdown ();
121 }
122
123
124 static void
125 check_revocation (void *cls)
126 {
127   GNUNET_REVOCATION_query (testpeers[0].cfg,
128                            &testpeers[1].pubkey,
129                            &revocation_remote_cb, NULL);
130 }
131
132
133 static void
134 revocation_cb (void *cls,
135                int is_valid)
136 {
137   testpeers[1].revok_handle = NULL;
138   if (GNUNET_NO == is_valid)
139   {
140     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
141                 "Revocation successful\n");
142     check_revocation (NULL);
143   }
144 }
145
146
147 static void
148 ego_cb (void *cls,
149         const struct GNUNET_IDENTITY_Ego *ego)
150 {
151   static int completed = 0;
152
153   if ((NULL != ego) && (cls == &testpeers[0]))
154   {
155     testpeers[0].ego_lookup = NULL;
156     testpeers[0].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
157     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[0].pubkey);
158     completed++;
159   }
160   if ((NULL != ego) && (cls == &testpeers[1]))
161   {
162     testpeers[1].ego_lookup = NULL;
163     testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
164     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey);
165     GNUNET_REVOCATION_sign_revocation (testpeers[1].privkey, &testpeers[1].sig);
166
167     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
168                "Calculating proof of work...\n");
169     testpeers[1].pow = 0;
170     int res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
171         testpeers[1].pow, 5);
172     while (GNUNET_OK != res)
173     {
174       testpeers[1].pow++;
175       res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
176                                          testpeers[1].pow,
177                                          5);
178     }
179     fprintf (stderr,
180              "Done calculating proof of work\n");
181     completed++;
182   }
183   if (2 == completed)
184   {
185     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
186                "Egos retrieved\n");
187     testpeers[1].revok_handle
188       = GNUNET_REVOCATION_revoke (testpeers[1].cfg,
189                                   &testpeers[1].pubkey,
190                                   &testpeers[1].sig,
191                                   testpeers[1].pow,
192                                   &revocation_cb, NULL);
193   }
194 }
195
196
197 static void
198 identity_create_cb (void *cls,
199                     const char *emsg)
200 {
201   static int completed = 0;
202
203   if ((NULL == emsg) && (cls == &testpeers[0]))
204   {
205     testpeers[0].create_id_op = NULL;
206     completed++;
207   }
208   if ((NULL == emsg) && (cls == &testpeers[1]))
209   {
210     testpeers[1].create_id_op = NULL;
211     completed++;
212   }
213   if (2 != completed)
214     return;
215   fprintf (stderr,
216            "Identities created\n");
217   testpeers[0].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[0].cfg,
218                                                         "client",
219                                                         &ego_cb,
220                                                         &testpeers[0]);
221   testpeers[1].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[1].cfg,
222                                                         "toberevoked",
223                                                         &ego_cb,
224                                                         &testpeers[1]);
225 }
226
227
228 static void
229 identity_completion_cb (void *cls,
230                         struct GNUNET_TESTBED_Operation *op,
231                         void *ca_result,
232                         const char *emsg)
233 {
234   static int completed = 0;
235
236   completed++;
237   if (NUM_TEST_PEERS != completed)
238     return;
239   fprintf (stderr,
240            "All peers connected @ IDENTITY ...\n");
241   testpeers[0].create_id_op
242     = GNUNET_IDENTITY_create (testpeers[0].idh,
243                               "client",
244                               &identity_create_cb,
245                               &testpeers[0]);
246   testpeers[1].create_id_op
247     = GNUNET_IDENTITY_create (testpeers[1].idh,
248                               "toberevoked",
249                               &identity_create_cb,
250                               &testpeers[1]);
251 }
252
253
254 static void *
255 identity_connect_adapter (void *cls,
256                           const struct GNUNET_CONFIGURATION_Handle *cfg)
257 {
258   struct TestPeer *me = cls;
259
260   me->cfg = cfg;
261   me->idh = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
262   if (NULL == me->idh)
263     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
264                 "Failed to create IDENTITY handle \n");
265   return me->idh;
266 }
267
268
269 static void
270 identity_disconnect_adapter (void *cls,
271                              void *op_result)
272 {
273   struct TestPeer *me = cls;
274   GNUNET_IDENTITY_disconnect (me->idh);
275   me->idh = NULL;
276 }
277
278
279 static void *
280 connect_cb (void *cls,
281             const struct GNUNET_PeerIdentity *peer,
282             struct GNUNET_MQ_Handle *mq)
283 {
284   static int connects = 0;
285
286   connects++;
287   if (NUM_TEST_PEERS * NUM_TEST_PEERS == connects)
288   {
289     fprintf (stderr,
290              "All peers connected @ CORE ...\n");
291
292     /* Connect to identity service */
293     testpeers[0].identity_op
294       = GNUNET_TESTBED_service_connect (NULL,
295                                         testpeers[0].p, "identity",
296                                         &identity_completion_cb, NULL,
297                                         &identity_connect_adapter,
298                                         &identity_disconnect_adapter,
299                                         &testpeers[0]);
300     testpeers[1].identity_op
301       = GNUNET_TESTBED_service_connect (NULL,
302                                         testpeers[1].p, "identity",
303                                         *identity_completion_cb, NULL,
304                                         &identity_connect_adapter,
305                                         &identity_disconnect_adapter,
306                                         &testpeers[1]);
307   }
308   return NULL;
309 }
310
311
312 static void
313 core_completion_cb (void *cls,
314                     struct GNUNET_TESTBED_Operation *op,
315                     void *ca_result,
316                     const char *emsg)
317 {
318   static int completed = 0;
319
320   completed++;
321   if (NUM_TEST_PEERS == completed)
322   {
323     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
324                 "Connected to CORE\n");
325   }
326 }
327
328
329 static void *
330 core_connect_adapter (void *cls,
331                       const struct GNUNET_CONFIGURATION_Handle *cfg)
332 {
333   struct TestPeer *me = cls;
334
335   me->cfg = cfg;
336   me->ch = GNUNET_CORE_connect (cfg,
337                                 me,
338                                 NULL,
339                                 &connect_cb,
340                                 NULL,
341                                 NULL);
342   if (NULL == me->ch)
343     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
344                "Failed to create CORE handle \n");
345   return me->ch;
346 }
347
348
349 static void
350 core_disconnect_adapter (void *cls,
351                          void *op_result)
352 {
353   struct TestPeer *me = cls;
354
355   GNUNET_CORE_disconnect (me->ch);
356   me->ch = NULL;
357 }
358
359
360 static void
361 test_connection (void *cls,
362                  struct GNUNET_TESTBED_RunHandle *h,
363                  unsigned int num_peers,
364                  struct GNUNET_TESTBED_Peer **peers,
365                  unsigned int links_succeeded,
366                  unsigned int links_failed)
367 {
368   unsigned int c;
369
370   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
371                                  NULL);
372   if (NUM_TEST_PEERS != num_peers)
373   {
374     ok = 4;
375     fprintf (stderr,
376              "Only %u out of %u peers were started ...\n",
377              num_peers,
378              NUM_TEST_PEERS);
379     GNUNET_SCHEDULER_shutdown ();
380     return;
381   }
382    /* We are generating a CLIQUE */
383   if (NUM_TEST_PEERS * (NUM_TEST_PEERS -1) == links_succeeded)
384   {
385     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
386                 "Testbed connected peers, initializing test\n");
387     for (c = 0; c < num_peers; c++)
388     {
389       testpeers[c].p = peers[c];
390       testpeers[c].core_op
391         = GNUNET_TESTBED_service_connect (NULL,
392                                           testpeers[c].p,
393                                           "core",
394                                           &core_completion_cb, NULL,
395                                           &core_connect_adapter,
396                                           &core_disconnect_adapter,
397                                           &testpeers[c]);
398     }
399   }
400   else
401   {
402     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403                 "Testbed failed to connect peers\n");
404     ok = 5;
405     GNUNET_SCHEDULER_shutdown ();
406     return;
407   }
408 }
409
410
411 int
412 main (int argc,
413       char *argv[])
414 {
415   ok = 1;
416   /* Connecting initial topology */
417   (void) GNUNET_TESTBED_test_run ("test-revocation",
418                                   "test_revocation.conf",
419                                   NUM_TEST_PEERS, 0,
420                                   NULL, NULL,
421                                   &test_connection, NULL);
422   return ok;
423 }
424
425 /* end of test_revocation.c */