aboutsummaryrefslogtreecommitdiff
path: root/src/contrib/service/abd/abd_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/service/abd/abd_api.c')
-rw-r--r--src/contrib/service/abd/abd_api.c563
1 files changed, 563 insertions, 0 deletions
diff --git a/src/contrib/service/abd/abd_api.c b/src/contrib/service/abd/abd_api.c
new file mode 100644
index 000000000..3682f41ba
--- /dev/null
+++ b/src/contrib/service/abd/abd_api.c
@@ -0,0 +1,563 @@
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 abd/abd_api.c
22 * @brief library to access the ABD service
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_protocols.h"
30#include "gnunet_signatures.h"
31#include "abd.h"
32#include "abd_serialization.h"
33#include "gnunet_abd_service.h"
34#include "gnunet_identity_service.h"
35
36
37#define LOG(kind, ...) GNUNET_log_from (kind, "abd-api", __VA_ARGS__)
38
39/**
40 * Handle to a verify request
41 */
42struct GNUNET_ABD_Request
43{
44
45 /**
46 * DLL
47 */
48 struct GNUNET_ABD_Request *next;
49
50 /**
51 * DLL
52 */
53 struct GNUNET_ABD_Request *prev;
54
55 /**
56 * handle to abd service
57 */
58 struct GNUNET_ABD_Handle *abd_handle;
59
60 /**
61 * processor to call on verify result
62 */
63 GNUNET_ABD_CredentialResultProcessor verify_proc;
64
65 /**
66 * @e verify_proc closure
67 */
68 void *proc_cls;
69
70 /**
71 * processor to call on intermediate result
72 */
73 GNUNET_ABD_IntermediateResultProcessor int_proc;
74
75 /**
76 * @e verify_proc2 closure
77 */
78 void *proc2_cls;
79
80 /**
81 * Envelope with the message for this queue entry.
82 */
83 struct GNUNET_MQ_Envelope *env;
84
85 /**
86 * request id
87 */
88 uint32_t r_id;
89};
90
91
92/**
93 * Connection to the ABD service.
94 */
95struct GNUNET_ABD_Handle
96{
97
98 /**
99 * Configuration to use.
100 */
101 const struct GNUNET_CONFIGURATION_Handle *cfg;
102
103 /**
104 * Connection to service (if available).
105 */
106 struct GNUNET_MQ_Handle *mq;
107
108 /**
109 * Head of linked list of active verify requests.
110 */
111 struct GNUNET_ABD_Request *request_head;
112
113 /**
114 * Tail of linked list of active verify requests.
115 */
116 struct GNUNET_ABD_Request *request_tail;
117
118 /**
119 * Reconnect task
120 */
121 struct GNUNET_SCHEDULER_Task *reconnect_task;
122
123 /**
124 * How long do we wait until we try to reconnect?
125 */
126 struct GNUNET_TIME_Relative reconnect_backoff;
127
128 /**
129 * Request Id generator. Incremented by one for each request.
130 */
131 uint32_t r_id_gen;
132};
133
134
135/**
136 * Reconnect to ABD service.
137 *
138 * @param handle the handle to the ABD service
139 */
140static void
141reconnect (struct GNUNET_ABD_Handle *handle);
142
143
144/**
145 * Reconnect to ABD
146 *
147 * @param cls the handle
148 */
149static void
150reconnect_task (void *cls)
151{
152 struct GNUNET_ABD_Handle *handle = cls;
153
154 handle->reconnect_task = NULL;
155 reconnect (handle);
156}
157
158
159/**
160 * Disconnect from service and then reconnect.
161 *
162 * @param handle our handle
163 */
164static void
165force_reconnect (struct GNUNET_ABD_Handle *handle)
166{
167 GNUNET_MQ_destroy (handle->mq);
168 handle->mq = NULL;
169 handle->reconnect_backoff =
170 GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
171 handle->reconnect_task =
172 GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
173 &reconnect_task,
174 handle);
175}
176
177
178/**
179 * Generic error handler, called with the appropriate error code and
180 * the same closure specified at the creation of the message queue.
181 * Not every message queue implementation supports an error handler.
182 *
183 * @param cls closure with the `struct GNUNET_ABD_Handle *`
184 * @param error error code
185 */
186static void
187mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
188{
189 struct GNUNET_ABD_Handle *handle = cls;
190
191 force_reconnect (handle);
192}
193
194
195/**
196 * Check validity of message received from the ABD service
197 *
198 * @param cls the `struct GNUNET_ABD_Handle *`
199 * @param vr_msg the incoming message
200 */
201static int
202check_result (void *cls, const struct DelegationChainResultMessage *vr_msg)
203{
204 // TODO
205 return GNUNET_OK;
206}
207
208
209/**
210 * Handler for messages received from the ABD service
211 *
212 * @param cls the `struct GNUNET_ABD_Handle *`
213 * @param vr_msg the incoming message
214 */
215static void
216handle_result (void *cls, const struct DelegationChainResultMessage *vr_msg)
217{
218 struct GNUNET_ABD_Handle *handle = cls;
219 uint32_t r_id = ntohl (vr_msg->id);
220 struct GNUNET_ABD_Request *vr;
221 size_t mlen = ntohs (vr_msg->header.size) - sizeof (*vr_msg);
222 uint32_t d_count = ntohl (vr_msg->d_count);
223 uint32_t c_count = ntohl (vr_msg->c_count);
224 struct GNUNET_ABD_Delegation d_chain[d_count];
225 struct GNUNET_ABD_Delegate dels[c_count];
226 GNUNET_ABD_CredentialResultProcessor proc;
227 void *proc_cls;
228
229 LOG (GNUNET_ERROR_TYPE_DEBUG,
230 "Received verify reply from ABD service\n");
231 for (vr = handle->request_head; NULL != vr; vr = vr->next)
232 if (vr->r_id == r_id)
233 break;
234 if (NULL == vr)
235 return;
236 proc = vr->verify_proc;
237 proc_cls = vr->proc_cls;
238 GNUNET_CONTAINER_DLL_remove (handle->request_head, handle->request_tail, vr);
239 GNUNET_MQ_discard (vr->env);
240 GNUNET_free (vr);
241 GNUNET_assert (
242 GNUNET_OK ==
243 GNUNET_ABD_delegation_chain_deserialize (mlen,
244 (const char *) &vr_msg[1],
245 d_count,
246 d_chain,
247 c_count,
248 dels));
249 if (GNUNET_NO == ntohl (vr_msg->del_found))
250 {
251 proc (proc_cls, 0, NULL, 0,
252 NULL);
253 }
254 else
255 {
256 proc (proc_cls, d_count, d_chain, c_count, dels);
257 }
258}
259
260
261static int
262check_intermediate (void *cls, const struct
263 DelegationChainIntermediateMessage *vr_msg)
264{
265 // TODO
266 return GNUNET_OK;
267}
268
269
270static void
271handle_intermediate (void *cls, const struct
272 DelegationChainIntermediateMessage *vr_msg)
273{
274 struct GNUNET_ABD_Handle *handle = cls;
275 uint32_t r_id = ntohl (vr_msg->id);
276 uint32_t size = ntohl (vr_msg->size);
277 bool is_bw = ntohs (vr_msg->is_bw);
278 struct GNUNET_ABD_Request *vr;
279 GNUNET_ABD_IntermediateResultProcessor proc;
280 void *proc_cls;
281 struct GNUNET_ABD_Delegation *dd;
282
283
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Received intermediate reply from ABD service\n");
286
287 for (vr = handle->request_head; NULL != vr; vr = vr->next)
288 if (vr->r_id == r_id)
289 break;
290 if (NULL == vr)
291 return;
292
293 proc = vr->int_proc;
294 proc_cls = vr->proc2_cls;
295
296 dd = GNUNET_new (struct GNUNET_ABD_Delegation);
297 GNUNET_assert (
298 GNUNET_OK ==
299 GNUNET_ABD_delegation_chain_deserialize (size,
300 (const char *) &vr_msg[1],
301 1,
302 dd,
303 0,
304 NULL));
305 proc (proc_cls, dd, is_bw);
306}
307
308
309/**
310 * Reconnect to ABD service.
311 *
312 * @param handle the handle to the ABD service
313 */
314static void
315reconnect (struct GNUNET_ABD_Handle *handle)
316{
317 struct GNUNET_MQ_MessageHandler handlers[] =
318 {GNUNET_MQ_hd_var_size (result,
319 GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT,
320 struct DelegationChainResultMessage,
321 handle),
322 GNUNET_MQ_hd_var_size (result,
323 GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT,
324 struct DelegationChainResultMessage,
325 handle),
326 GNUNET_MQ_hd_var_size (intermediate,
327 GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT,
328 struct DelegationChainIntermediateMessage,
329 handle),
330 GNUNET_MQ_handler_end ()};
331 struct GNUNET_ABD_Request *vr;
332
333 GNUNET_assert (NULL == handle->mq);
334 LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to ABD\n");
335 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
336 "abd",
337 handlers,
338 &mq_error_handler,
339 handle);
340 if (NULL == handle->mq)
341 return;
342 for (vr = handle->request_head; NULL != vr; vr = vr->next)
343 GNUNET_MQ_send_copy (handle->mq, vr->env);
344}
345
346
347/**
348 * Initialize the connection with the ABD service.
349 *
350 * @param cfg configuration to use
351 * @return handle to the ABD service, or NULL on error
352 */
353struct GNUNET_ABD_Handle *
354GNUNET_ABD_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
355{
356 struct GNUNET_ABD_Handle *handle;
357
358 handle = GNUNET_new (struct GNUNET_ABD_Handle);
359 handle->cfg = cfg;
360 reconnect (handle);
361 if (NULL == handle->mq)
362 {
363 GNUNET_free (handle);
364 return NULL;
365 }
366 return handle;
367}
368
369
370/**
371 * Shutdown connection with the ABD service.
372 *
373 * @param handle handle of the ABD connection to stop
374 */
375void
376GNUNET_ABD_disconnect (struct GNUNET_ABD_Handle *handle)
377{
378 if (NULL != handle->mq)
379 {
380 GNUNET_MQ_destroy (handle->mq);
381 handle->mq = NULL;
382 }
383 if (NULL != handle->reconnect_task)
384 {
385 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
386 handle->reconnect_task = NULL;
387 }
388 GNUNET_assert (NULL == handle->request_head);
389 GNUNET_free (handle);
390}
391
392
393/**
394 * Cancel pending verify request
395 *
396 * @param lr the verify request to cancel
397 */
398void
399GNUNET_ABD_request_cancel (struct GNUNET_ABD_Request *lr)
400{
401 struct GNUNET_ABD_Handle *handle = lr->abd_handle;
402
403 GNUNET_CONTAINER_DLL_remove (handle->request_head, handle->request_tail, lr);
404 GNUNET_MQ_discard (lr->env);
405 GNUNET_free (lr);
406}
407
408
409/**
410 * Performs attribute collection.
411 * Collects all abds of subject to fulfill the
412 * attribute, if possible
413 *
414 * @param handle handle to the Credential service
415 * @param issuer_key the issuer public key
416 * @param issuer_attribute the issuer attribute
417 * @param subject_key the subject public key
418 * @param proc function to call on result
419 * @param proc_cls closure for processor
420 * @return handle to the queued request
421 */
422struct GNUNET_ABD_Request *
423GNUNET_ABD_collect (
424 struct GNUNET_ABD_Handle *handle,
425 const struct GNUNET_CRYPTO_PublicKey *issuer_key,
426 const char *issuer_attribute,
427 const struct GNUNET_CRYPTO_PrivateKey *subject_key,
428 enum GNUNET_ABD_AlgoDirectionFlags direction,
429 GNUNET_ABD_CredentialResultProcessor proc,
430 void *proc_cls,
431 GNUNET_ABD_IntermediateResultProcessor proc2,
432 void *proc2_cls)
433{
434 /* IPC to shorten abd names, return shorten_handle */
435 struct CollectMessage *c_msg;
436 struct GNUNET_ABD_Request *vr;
437 size_t nlen;
438
439 if (NULL == issuer_attribute)
440 {
441 GNUNET_break (0);
442 return NULL;
443 }
444
445 // DEBUG LOG
446 LOG (GNUNET_ERROR_TYPE_DEBUG,
447 "Trying to collect `%s' in ABD\n",
448 issuer_attribute);
449 nlen = strlen (issuer_attribute) + 1;
450 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
451 {
452 GNUNET_break (0);
453 return NULL;
454 }
455 vr = GNUNET_new (struct GNUNET_ABD_Request);
456 vr->abd_handle = handle;
457 vr->verify_proc = proc;
458 vr->proc_cls = proc_cls;
459 vr->int_proc = proc2;
460 vr->proc2_cls = proc2_cls;
461 vr->r_id = handle->r_id_gen++;
462 vr->env =
463 GNUNET_MQ_msg_extra (c_msg, nlen, GNUNET_MESSAGE_TYPE_ABD_COLLECT);
464 c_msg->id = htonl (vr->r_id);
465 c_msg->subject_key = *subject_key;
466 c_msg->issuer_key = *issuer_key;
467 c_msg->issuer_attribute_len = htons (strlen (issuer_attribute));
468 c_msg->resolution_algo = htons (direction);
469
470 GNUNET_memcpy (&c_msg[1], issuer_attribute, strlen (issuer_attribute));
471 GNUNET_CONTAINER_DLL_insert (handle->request_head, handle->request_tail, vr);
472 if (NULL != handle->mq)
473 GNUNET_MQ_send_copy (handle->mq, vr->env);
474 return vr;
475}
476
477
478/**
479 * Performs attribute verification.
480 * Checks if there is a delegation chain from
481 * attribute ``issuer_attribute'' issued by the issuer
482 * with public key ``issuer_key'' maps to the attribute
483 * ``subject_attribute'' claimed by the subject with key
484 * ``subject_key''
485 *
486 * @param handle handle to the Credential service
487 * @param issuer_key the issuer public key
488 * @param issuer_attribute the issuer attribute
489 * @param subject_key the subject public key
490 * @param delegate_count number of delegates provided
491 * @param delegates subject delegates
492 * @param proc function to call on result
493 * @param proc_cls closure for processor
494 * @return handle to the queued request
495 */
496struct GNUNET_ABD_Request *
497GNUNET_ABD_verify (
498 struct GNUNET_ABD_Handle *handle,
499 const struct GNUNET_CRYPTO_PublicKey *issuer_key,
500 const char *issuer_attribute,
501 const struct GNUNET_CRYPTO_PublicKey *subject_key,
502 uint32_t delegate_count,
503 const struct GNUNET_ABD_Delegate *delegates,
504 enum GNUNET_ABD_AlgoDirectionFlags direction,
505 GNUNET_ABD_CredentialResultProcessor proc,
506 void *proc_cls,
507 GNUNET_ABD_IntermediateResultProcessor proc2,
508 void *proc2_cls)
509{
510 /* IPC to shorten abd names, return shorten_handle */
511 struct VerifyMessage *v_msg;
512 struct GNUNET_ABD_Request *vr;
513 size_t nlen;
514 size_t clen;
515
516 if ((NULL == issuer_attribute) || (NULL == delegates))
517 {
518 GNUNET_break (0);
519 return NULL;
520 }
521
522 clen = GNUNET_ABD_delegates_get_size (delegate_count, delegates);
523
524 // DEBUG LOG
525 LOG (GNUNET_ERROR_TYPE_DEBUG,
526 "Trying to verify `%s' in ABD\n",
527 issuer_attribute);
528 nlen = strlen (issuer_attribute) + 1 + clen;
529 if (nlen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*vr))
530 {
531 GNUNET_break (0);
532 return NULL;
533 }
534 vr = GNUNET_new (struct GNUNET_ABD_Request);
535 vr->abd_handle = handle;
536 vr->verify_proc = proc;
537 vr->proc_cls = proc_cls;
538 vr->int_proc = proc2;
539 vr->proc2_cls = proc2_cls;
540 vr->r_id = handle->r_id_gen++;
541 vr->env =
542 GNUNET_MQ_msg_extra (v_msg, nlen, GNUNET_MESSAGE_TYPE_ABD_VERIFY);
543 v_msg->id = htonl (vr->r_id);
544 v_msg->subject_key = *subject_key;
545 v_msg->d_count = htonl (delegate_count);
546 v_msg->issuer_key = *issuer_key;
547 v_msg->issuer_attribute_len = htons (strlen (issuer_attribute));
548 v_msg->resolution_algo = htons (direction);
549
550 GNUNET_memcpy (&v_msg[1], issuer_attribute, strlen (issuer_attribute));
551 GNUNET_ABD_delegates_serialize (delegate_count,
552 delegates,
553 clen,
554 ((char *) &v_msg[1])
555 + strlen (issuer_attribute) + 1);
556 GNUNET_CONTAINER_DLL_insert (handle->request_head, handle->request_tail, vr);
557 if (NULL != handle->mq)
558 GNUNET_MQ_send_copy (handle->mq, vr->env);
559 return vr;
560}
561
562
563/* end of abd_api.c */