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