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