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,
261 * Get serialized record data size
263 len = attr_record_count * sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData);
266 * Prepare a lookup result response message for the client
268 env = GNUNET_MQ_msg_extra (rmsg,
270 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT);
271 //Assign id so that client can find associated request
272 rmsg->id = vrh->request_id;
273 rmsg->ad_count = htonl (attr_record_count);
276 * Get serialized record data
277 * Append at the end of rmsg
280 struct GNUNET_CREDENTIAL_AttributeRecordData *tmp_record = (struct GNUNET_CREDENTIAL_AttributeRecordData*) &rmsg[1];
281 for (ar_entry = vrh->attr_chain_head; NULL != ar_entry; ar_entry = ar_entry->next)
284 &ar_entry->record_data,
285 sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData));
288 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(vrh->client),
291 GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
296 * - Refactor into cleanup_handle() function for this
300 GNUNET_STATISTICS_update (statistics,
301 "Completed verifications", 1,
303 GNUNET_STATISTICS_update (statistics,
304 "Attributes resolved",
310 * Handle attribute verification requests from client
312 * @param cls the closure
313 * @param client the client
314 * @param message the message
317 handle_verify (void *cls,
318 const struct VerifyMessage *v_msg)
320 char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
321 char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
322 size_t issuer_attribute_len;
323 struct VerifyRequestHandle *vrh;
324 struct GNUNET_SERVICE_Client *client = cls;
325 char *attrptr = issuer_attribute;
328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
329 "Received VERIFY message\n");
331 utf_in = (const char *) &v_msg[1];
332 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
333 issuer_attribute_len = strlen (utf_in);
334 utf_in = (const char *) (&v_msg[1] + issuer_attribute_len + 1);
335 attrptr = subject_attribute;
336 GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
337 vrh = GNUNET_new (struct VerifyRequestHandle);
338 GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
339 vrh->client = client;
340 vrh->request_id = v_msg->id;
341 vrh->issuer_key = v_msg->issuer_key;
342 vrh->subject_key = v_msg->subject_key;
344 if (NULL == subject_attribute)
346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
347 "No subject attribute provided!\n");
348 send_lookup_response (vrh, 0, NULL);
351 if (NULL == issuer_attribute)
353 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354 "No issuer attribute provided!\n");
355 send_lookup_response (vrh, 0, NULL);
359 * First, get attribute from subject
361 vrh->lookup_request = GNUNET_GNS_lookup (gns,
363 &v_msg->subject_key, //subject_pkey,
364 GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
365 GNUNET_GNS_LO_DEFAULT,
366 NULL, //shorten_key, always NULL
367 &send_lookup_response,
373 * One of our clients disconnected, clean up after it.
376 * @param client the client that disconnected
379 client_disconnect_cb (void *cls,
380 struct GNUNET_SERVICE_Client *client,
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Client %p disconnected\n",
389 * Add a client to our list of active clients.
392 * @param client client to add
393 * @param mq message queue for @a client
394 * @return this client
397 client_connect_cb (void *cls,
398 struct GNUNET_SERVICE_Client *client,
399 struct GNUNET_MQ_Handle *mq)
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "Client %p connected\n",
408 * Process Credential requests.
411 * @param server the initialized server
412 * @param c configuration to use
416 const struct GNUNET_CONFIGURATION_Handle *c,
417 struct GNUNET_SERVICE_Handle *handle)
420 gns = GNUNET_GNS_connect (c);
424 _("Failed to connect to GNS\n"));
427 statistics = GNUNET_STATISTICS_create ("credential", c);
428 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
433 * Define "main" method using service macro
437 GNUNET_SERVICE_OPTION_NONE,
440 &client_disconnect_cb,
442 GNUNET_MQ_hd_var_size (verify,
443 GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
444 struct VerifyMessage,
446 GNUNET_MQ_handler_end());
448 /* end of gnunet-service-credential.c */