2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 GNUnet e.V.
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.
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.
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.
21 * @file gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
26 #include "gnunet_util_lib.h"
27 #include "gnunet_credential_service.h"
28 #include "gnunet_statistics_service.h"
29 #include "credential.h"
30 #include "gnunet_protocols.h"
32 // For Looking up GNS request
33 #include <gnunet_dnsparser_lib.h>
34 #include <gnunet_identity_service.h>
35 #include <gnunet_gnsrecord_lib.h>
36 #include <gnunet_namestore_service.h>
37 #include <gnunet_gns_service.h>
38 #include "gnunet_gns_service.h"
43 #define GNUNET_CREDENTIAL_MAX_LENGTH 255
48 struct AttributeRecordEntry
53 struct AttributeRecordEntry *next;
58 struct AttributeRecordEntry *prev;
64 struct GNUNET_CREDENTIAL_AttributeRecordData record_data;
68 * Handle to a lookup operation from api
70 struct VerifyRequestHandle
74 * We keep these in a DLL.
76 struct VerifyRequestHandle *next;
79 * We keep these in a DLL.
81 struct VerifyRequestHandle *prev;
84 * Handle to the requesting client
86 struct GNUNET_SERVICE_Client *client;
89 * Handle to GNS lookup
91 struct GNUNET_GNS_LookupRequest *lookup_request;
96 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
101 struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
106 struct AttributeRecordEntry *attr_chain_head;
111 struct AttributeRecordEntry *attr_chain_tail;
124 static struct VerifyRequestHandle *vrh_head;
129 static struct VerifyRequestHandle *vrh_tail;
132 * Handle to the statistics service
134 static struct GNUNET_STATISTICS_Handle *statistics;
139 * Handle to GNS service.
141 static struct GNUNET_GNS_Handle *gns;
144 * Task run during shutdown.
150 shutdown_task (void *cls)
152 struct VerifyRequestHandle *vrh;
154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156 while (NULL != (vrh = vrh_head))
158 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
159 GNUNET_CONTAINER_DLL_remove (vrh_head,
166 if (NULL != statistics)
168 GNUNET_STATISTICS_destroy (statistics,
176 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
178 * @param cls client sending the message
179 * @param v_msg message of type `struct VerifyMessage`
180 * @return #GNUNET_OK if @a v_msg is well-formed
183 check_verify (void *cls,
184 const struct VerifyMessage *v_msg)
191 msg_size = ntohs (v_msg->header.size);
192 if (msg_size < sizeof (struct VerifyMessage))
195 return GNUNET_SYSERR;
197 i_attr = (const char *) &v_msg[1];
198 if ( ('\0' != i_attr[v_msg->header.size - sizeof (struct VerifyMessage) - 1]) ||
199 (strlen (i_attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
202 return GNUNET_SYSERR;
204 attr_len = strlen (i_attr);
205 s_attr = ((const char *) &v_msg[1]) + attr_len + 1;
206 if ( ('\0' != s_attr[v_msg->header.size - sizeof (struct VerifyMessage) - 1]) ||
207 (strlen (s_attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
210 return GNUNET_SYSERR;
217 * Result from GNS lookup.
219 * @param cls the closure (our client lookup handle)
220 * @param rd_count the number of records in @a rd
221 * @param rd the record data
224 send_lookup_response (void* cls,
226 const struct GNUNET_GNSRECORD_Data *rd)
228 struct VerifyRequestHandle *vrh = cls;
231 int attr_record_count;
232 struct GNUNET_MQ_Envelope *env;
233 struct VerifyResultMessage *rmsg;
234 const struct GNUNET_CREDENTIAL_AttributeRecordData *ard;
235 struct AttributeRecordEntry *ar_entry;
237 attr_record_count = 0;
238 for (i=0; i < rd_count; i++)
240 if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
246 * Check if we have already found our credential here
247 * If so return success
249 * Save all found attributes/issues and prepare forward
250 * resolution of issuer attribute
252 ar_entry = GNUNET_new (struct AttributeRecordEntry);
253 ar_entry->record_data = *ard;
254 GNUNET_CONTAINER_DLL_insert_tail (vrh->attr_chain_head,
255 vrh->attr_chain_tail,
262 * Start resolution of Attribute delegations from issuer
264 * - Build adequate data structures for attribute(s) to lookup
265 * - Use GNUNET_GNSRECORD_TYPE_XXX
266 * - recursively try to find match(es) with results found top
267 * - return one found credential chain
272 * Get serialized record data size
274 len = attr_record_count * sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData);
277 * Prepare a lookup result response message for the client
279 env = GNUNET_MQ_msg_extra (rmsg,
281 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
282 //Assign id so that client can find associated request
283 rmsg->id = vrh->request_id;
284 rmsg->ad_count = htonl (attr_record_count);
287 * Get serialized record data
288 * Append at the end of rmsg
291 struct GNUNET_CREDENTIAL_AttributeRecordData *tmp_record = (struct GNUNET_CREDENTIAL_AttributeRecordData*) &rmsg[1];
292 for (ar_entry = vrh->attr_chain_head; NULL != ar_entry; ar_entry = ar_entry->next)
295 &ar_entry->record_data,
296 sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData));
299 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
302 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
307 * - Refactor into cleanup_handle() function for this
311 GNUNET_STATISTICS_update (statistics,
312 "Completed verifications", 1,
314 GNUNET_STATISTICS_update (statistics,
315 "Attributes resolved",
321 * Handle attribute verification requests from client
323 * @param cls the closure
324 * @param client the client
325 * @param message the message
328 handle_verify (void *cls,
329 const struct VerifyMessage *v_msg)
331 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
332 char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
333 size_t issuer_attribute_len;
334 struct VerifyRequestHandle *vrh;
335 struct GNUNET_SERVICE_Client *client = cls;
336 char *attrptr = issuer_attribute;
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
340 "Received VERIFY message\n");
342 utf_in = (const char *) &v_msg[1];
343 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
344 issuer_attribute_len = strlen (utf_in);
345 utf_in = (const char *) (&v_msg[1] + issuer_attribute_len + 1);
346 attrptr = subject_attribute;
347 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
348 vrh = GNUNET_new (struct VerifyRequestHandle);
349 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
350 vrh->client = client;
351 vrh->request_id = v_msg->id;
352 vrh->issuer_key = v_msg->issuer_key;
353 vrh->subject_key = v_msg->subject_key;
355 if (NULL == subject_attribute)
357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
358 "No subject attribute provided!\n");
359 send_lookup_response (vrh, 0, NULL);
362 if (NULL == issuer_attribute)
364 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
365 "No issuer attribute provided!\n");
366 send_lookup_response (vrh, 0, NULL);
370 * First, get attribute from subject
372 vrh->lookup_request = GNUNET_GNS_lookup (gns,
374 &v_msg->subject_key, //subject_pkey,
375 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
376 GNUNET_GNS_LO_DEFAULT,
377 NULL, //shorten_key, always NULL
378 &send_lookup_response,
384 * One of our clients disconnected, clean up after it.
387 * @param client the client that disconnected
390 client_disconnect_cb (void *cls,
391 struct GNUNET_SERVICE_Client *client,
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "Client %p disconnected\n",
400 * Add a client to our list of active clients.
403 * @param client client to add
404 * @param mq message queue for @a client
405 * @return this client
408 client_connect_cb (void *cls,
409 struct GNUNET_SERVICE_Client *client,
410 struct GNUNET_MQ_Handle *mq)
412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
413 "Client %p connected\n",
419 * Process Credential requests.
422 * @param server the initialized server
423 * @param c configuration to use
427 const struct GNUNET_CONFIGURATION_Handle *c,
428 struct GNUNET_SERVICE_Handle *handle)
431 gns = GNUNET_GNS_connect (c);
435 _("Failed to connect to GNS\n"));
438 statistics = GNUNET_STATISTICS_create ("credential", c);
439 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
444 * Define "main" method using service macro
448 GNUNET_SERVICE_OPTION_NONE,
451 &client_disconnect_cb,
453 GNUNET_MQ_hd_var_size (verify,
454 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
455 struct VerifyMessage,
457 GNUNET_MQ_handler_end());
459 /* end of gnunet-service-credential.c */