8ff66c57440d165bae5dc85a75a9251309535bb3
[oweals/gnunet.git] / src / credential / credential_api.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 credential/credential_api.c
22  * @brief library to access the CREDENTIAL service
23  * @author Adnan Husain
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_hello_lib.h"
30 #include "gnunet_protocols.h"
31 #include "credential.h"
32 #include "gnunet_credential_service.h"
33 #include "gnunet_identity_service.h"
34
35
36 #define LOG(kind,...) GNUNET_log_from (kind, "credential-api",__VA_ARGS__)
37
38 /**
39  * Handle to a verify request
40  */
41 struct GNUNET_CREDENTIAL_Request
42 {
43
44   /**
45    * DLL
46    */
47   struct GNUNET_CREDENTIAL_Request *next;
48
49   /**
50    * DLL
51    */
52   struct GNUNET_CREDENTIAL_Request *prev;
53
54   /**
55    * handle to credential service
56    */
57   struct GNUNET_CREDENTIAL_Handle *credential_handle;
58
59   /**
60    * processor to call on verify result
61    */
62   GNUNET_CREDENTIAL_VerifyResultProcessor verify_proc;
63
64   /**
65    * @e verify_proc closure
66    */
67   void *proc_cls;
68
69   /**
70    * Envelope with the message for this queue entry.
71    */
72   struct GNUNET_MQ_Envelope *env;
73
74   /**
75    * request id
76    */
77   uint32_t r_id;
78
79 };
80
81
82 /**
83  * Connection to the CREDENTIAL service.
84  */
85 struct GNUNET_CREDENTIAL_Handle
86 {
87
88   /**
89    * Configuration to use.
90    */
91   const struct GNUNET_CONFIGURATION_Handle *cfg;
92
93   /**
94    * Connection to service (if available).
95    */
96   struct GNUNET_MQ_Handle *mq;
97
98   /**
99    * Head of linked list of active verify requests.
100    */
101   struct GNUNET_CREDENTIAL_Request *verify_head;
102
103   /**
104    * Tail of linked list of active verify requests.
105    */
106   struct GNUNET_CREDENTIAL_Request *verify_tail;
107
108   /**
109    * Reconnect task
110    */
111   struct GNUNET_SCHEDULER_Task *reconnect_task;
112
113   /**
114    * How long do we wait until we try to reconnect?
115    */
116   struct GNUNET_TIME_Relative reconnect_backoff;
117
118   /**
119    * Request Id generator.  Incremented by one for each request.
120    */
121   uint32_t r_id_gen;
122
123 };
124
125
126 /**
127  * Reconnect to CREDENTIAL service.
128  *
129  * @param handle the handle to the CREDENTIAL service
130  */
131 static void
132 reconnect (struct GNUNET_CREDENTIAL_Handle *handle);
133
134
135 /**
136  * Reconnect to CREDENTIAL
137  *
138  * @param cls the handle
139  */
140 static void
141 reconnect_task (void *cls)
142 {
143   struct GNUNET_CREDENTIAL_Handle *handle = cls;
144
145   handle->reconnect_task = NULL;
146   reconnect (handle);
147 }
148
149
150 /**
151  * Disconnect from service and then reconnect.
152  *
153  * @param handle our handle
154  */
155 static void
156 force_reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
157 {
158   GNUNET_MQ_destroy (handle->mq);
159   handle->mq = NULL;
160   handle->reconnect_backoff
161     = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
162   handle->reconnect_task
163     = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
164                         &reconnect_task,
165                         handle);
166 }
167
168
169 /**
170  * Generic error handler, called with the appropriate error code and
171  * the same closure specified at the creation of the message queue.
172  * Not every message queue implementation supports an error handler.
173  *
174  * @param cls closure with the `struct GNUNET_CREDENTIAL_Handle *`
175  * @param error error code
176  */
177 static void
178 mq_error_handler (void *cls,
179                   enum GNUNET_MQ_Error error)
180 {
181   struct GNUNET_CREDENTIAL_Handle *handle = cls;
182
183   force_reconnect (handle);
184 }
185
186
187 /**
188  * Check validity of message received from the CREDENTIAL service
189  *
190  * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
191  * @param loookup_msg the incoming message
192  */
193 static int
194 check_result (void *cls,
195               const struct VerifyResultMessage *vr_msg)
196 {
197   //TODO
198   return GNUNET_OK;
199 }
200
201
202 /**
203  * Handler for messages received from the CREDENTIAL service
204  *
205  * @param cls the `struct GNUNET_CREDENTIAL_Handle *`
206  * @param loookup_msg the incoming message
207  */
208 static void
209 handle_result (void *cls,
210                const struct VerifyResultMessage *vr_msg)
211 {
212   struct GNUNET_CREDENTIAL_Handle *handle = cls;
213   uint32_t r_id = ntohl (vr_msg->id);
214   struct GNUNET_CREDENTIAL_Request *vr;
215   GNUNET_CREDENTIAL_VerifyResultProcessor proc;
216   void *proc_cls;
217
218   LOG (GNUNET_ERROR_TYPE_DEBUG,
219        "Received verify reply from CREDENTIAL service\n");
220   for (vr = handle->verify_head; NULL != vr; vr = vr->next)
221     if (vr->r_id == r_id)
222       break;
223   if (NULL == vr)
224     return;
225   proc = vr->verify_proc;
226   proc_cls = vr->proc_cls;
227   GNUNET_CONTAINER_DLL_remove (handle->verify_head,
228                                handle->verify_tail,
229                                vr);
230   GNUNET_free (vr);
231   /**
232   GNUNET_assert (GNUNET_OK ==
233                  GNUNET_CREDENTIAL_records_deserialize (mlen,
234                                                        (const char*) &lookup_msg[1],
235                                                        rd_count,
236                                                          rd));
237                                                          */
238   proc (proc_cls,
239         NULL,
240         GNUNET_NO); // TODO
241 }
242
243
244 /**
245  * Reconnect to CREDENTIAL service.
246  *
247  * @param handle the handle to the CREDENTIAL service
248  */
249 static void
250 reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
251 {
252   struct GNUNET_MQ_MessageHandler handlers[] = {
253     GNUNET_MQ_hd_var_size (result,
254                            GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
255                            struct VerifyResultMessage,
256                            NULL),
257     GNUNET_MQ_handler_end ()
258   };
259   struct GNUNET_CREDENTIAL_Request *vr;
260
261   GNUNET_assert (NULL == handle->mq);
262   LOG (GNUNET_ERROR_TYPE_DEBUG,
263        "Trying to connect to CREDENTIAL\n");
264   handle->mq = GNUNET_CLIENT_connecT (handle->cfg,
265                                       "credential",
266                                       handlers,
267                                       &mq_error_handler,
268                                       handle);
269   if (NULL == handle->mq)
270     return;
271   for (vr = handle->verify_head; NULL != vr; vr = vr->next)
272     GNUNET_MQ_send_copy (handle->mq,
273                          vr->env);
274 }
275
276
277 /**
278  * Initialize the connection with the CREDENTIAL service.
279  *
280  * @param cfg configuration to use
281  * @return handle to the CREDENTIAL service, or NULL on error
282  */
283 struct GNUNET_CREDENTIAL_Handle *
284 GNUNET_CREDENTIAL_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
285 {
286   struct GNUNET_CREDENTIAL_Handle *handle;
287
288   handle = GNUNET_new (struct GNUNET_CREDENTIAL_Handle);
289   handle->cfg = cfg;
290   reconnect (handle);
291   if (NULL == handle->mq)
292   {
293     GNUNET_free (handle);
294     return NULL;
295   }
296   return handle;
297 }
298
299
300 /**
301  * Shutdown connection with the CREDENTIAL service.
302  *
303  * @param handle handle of the CREDENTIAL connection to stop
304  */
305 void
306 GNUNET_CREDENTIAL_disconnect (struct GNUNET_CREDENTIAL_Handle *handle)
307 {
308   if (NULL != handle->mq)
309   {
310     GNUNET_MQ_destroy (handle->mq);
311     handle->mq = NULL;
312   }
313   if (NULL != handle->reconnect_task)
314   {
315     GNUNET_SCHEDULER_cancel (handle->reconnect_task);
316     handle->reconnect_task = NULL;
317   }
318   GNUNET_assert (NULL == handle->verify_head);
319   GNUNET_free (handle);
320 }
321
322
323 /**
324  * Cancel pending verify request
325  *
326  * @param lr the verify request to cancel
327  */
328 void
329 GNUNET_CREDENTIAL_verify_cancel (struct GNUNET_CREDENTIAL_Request *vr)
330 {
331   struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
332
333   GNUNET_CONTAINER_DLL_remove (handle->verify_head,
334                                handle->verify_tail,
335                                vr);
336   GNUNET_MQ_discard (vr->env);
337   GNUNET_free (vr);
338 }
339
340 /**
341  * Performs attribute verification.
342  * Checks if there is a delegation chain from
343  * attribute ``issuer_attribute'' issued by the issuer
344  * with public key ``issuer_key'' maps to the attribute
345  * ``subject_attribute'' claimed by the subject with key
346  * ``subject_key''
347  *
348  * @param handle handle to the Credential service
349  * @param issuer_key the issuer public key
350  * @param issuer_attribute the issuer attribute
351  * @param subject_key the subject public key
352  * @param subject_attribute the attribute claimed by the subject
353  * @param proc function to call on result
354  * @param proc_cls closure for processor
355  * @return handle to the queued request
356  */
357 struct GNUNET_CREDENTIAL_Request*
358 GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle *handle,
359                           const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
360                           const char *issuer_attribute,
361                           const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
362                           const char *subject_attribute,
363                           GNUNET_CREDENTIAL_VerifyResultProcessor proc,
364                           void *proc_cls)
365 {
366   /* IPC to shorten credential names, return shorten_handle */
367   struct VerifyMessage *v_msg;
368   struct GNUNET_CREDENTIAL_Request *vr;
369   size_t nlen;
370
371   if (NULL == issuer_attribute)
372   {
373     GNUNET_break (0);
374     return NULL;
375   }
376   //DEBUG LOG
377   LOG (GNUNET_ERROR_TYPE_DEBUG,
378        "Trying to verify `%s' in CREDENTIAL\n",
379        issuer_attribute);
380   nlen = strlen (issuer_attribute) + 1;
381   if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
382   {
383     GNUNET_break (0);
384     return NULL;
385   }
386   vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
387   vr->credential_handle = handle;
388   vr->verify_proc = proc;
389   vr->proc_cls = proc_cls;
390   vr->r_id = handle->r_id_gen++;
391   vr->env = GNUNET_MQ_msg_extra (v_msg,
392                                  nlen,
393                                  GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
394   v_msg->id = htonl (vr->r_id);
395   v_msg->subject_key = *subject_key;
396   v_msg->issuer_key =  *issuer_key;
397   GNUNET_memcpy (&v_msg[1],
398                  subject_attribute,
399                  nlen);
400   GNUNET_CONTAINER_DLL_insert (handle->verify_head,
401                                handle->verify_tail,
402                                vr);
403   if (NULL != handle->mq)
404     GNUNET_MQ_send_copy (handle->mq,
405                          vr->env);
406   return vr;
407 }
408
409
410 /* end of credential_api.c */