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 CredentialRecordEntry
53 struct CredentialRecordEntry *next;
58 struct CredentialRecordEntry *prev;
64 struct GNUNET_CREDENTIAL_RecordData record_data;
68 * Handle to a lookup operation from api
70 struct ClientLookupHandle
74 * We keep these in a DLL.
76 struct ClientLookupHandle *next;
79 * We keep these in a DLL.
81 struct ClientLookupHandle *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;
94 * Authority public key
96 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
101 struct CredentialRecordEntry *cred_chain_head;
106 struct CredentialRecordEntry *cred_chain_tail;
119 static struct ClientLookupHandle *clh_head;
124 static struct ClientLookupHandle *clh_tail;
127 * Handle to the statistics service
129 static struct GNUNET_STATISTICS_Handle *statistics;
134 * Handle to GNS service.
136 static struct GNUNET_GNS_Handle *gns;
139 * Task run during shutdown.
145 shutdown_task (void *cls)
147 struct ClientLookupHandle *clh;
149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151 while (NULL != (clh = clh_head))
153 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
154 GNUNET_CONTAINER_DLL_remove (clh_head,
161 if (NULL != statistics)
163 GNUNET_STATISTICS_destroy (statistics,
171 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP message
173 * @param cls client sending the message
174 * @param l_msg message of type `struct LookupMessage`
175 * @return #GNUNET_OK if @a l_msg is well-formed
178 check_lookup (void *cls,
179 const struct LookupMessage *l_msg)
184 msg_size = ntohs (l_msg->header.size);
185 if (msg_size < sizeof (struct LookupMessage))
188 return GNUNET_SYSERR;
190 cred = (const char *) &l_msg[1];
191 if ( ('\0' != cred[l_msg->header.size - sizeof (struct LookupMessage) - 1]) ||
192 (strlen (cred) > GNUNET_CREDENTIAL_MAX_LENGTH) )
195 return GNUNET_SYSERR;
202 * Reply to client with the result from our lookup.
204 * @param cls the closure (our client lookup handle)
205 * @param rd_count the number of records in @a rd
206 * @param rd the record data
209 send_lookup_response (void* cls,
211 const struct GNUNET_GNSRECORD_Data *rd)
213 struct ClientLookupHandle *clh = cls;
216 int cred_record_count;
217 struct GNUNET_MQ_Envelope *env;
218 struct LookupResultMessage *rmsg;
219 const struct GNUNET_CREDENTIAL_RecordData *crd;
220 struct CredentialRecordEntry *cr_entry;
222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223 "Sending LOOKUP_RESULT message with %u results\n",
224 (unsigned int) rd_count);
226 cred_record_count = 0;
227 for (i=0; i < rd_count; i++)
229 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
235 * - First time we come here subject must be subject prvided by client
236 * - After that is has to be the prev issuer
237 * - Terminate condition: issuer is clh->authority_key
240 * Append crd to result list of RecordData
242 cr_entry = GNUNET_new (struct CredentialRecordEntry);
243 cr_entry->record_data = *crd;
244 GNUNET_CONTAINER_DLL_insert_tail (clh->cred_chain_head,
245 clh->cred_chain_tail,
251 * Get serialized record data size
253 len = cred_record_count * sizeof (struct GNUNET_CREDENTIAL_RecordData);
256 * Prepare a lookup result response message for the client
258 env = GNUNET_MQ_msg_extra (rmsg,
260 GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP_RESULT);
261 //Assign id so that client can find associated request
262 rmsg->id = clh->request_id;
263 rmsg->cd_count = htonl (cred_record_count);
266 * Get serialized record data
267 * Append at the end of rmsg
270 struct GNUNET_CREDENTIAL_RecordData *tmp_record = (struct GNUNET_CREDENTIAL_RecordData*) &rmsg[1];
271 for (cr_entry = clh->cred_chain_head; NULL != cr_entry; cr_entry = cr_entry->next)
274 &cr_entry->record_data,
275 sizeof (struct GNUNET_CREDENTIAL_RecordData));
278 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->client),
281 GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh);
286 * - Refactor into cleanup_handle() function for this
290 GNUNET_STATISTICS_update (statistics,
291 "Completed lookups", 1,
293 GNUNET_STATISTICS_update (statistics,
300 * Handle lookup requests from client
302 * @param cls the closure
303 * @param client the client
304 * @param message the message
307 handle_lookup (void *cls,
308 const struct LookupMessage *l_msg)
310 char credential[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
311 struct ClientLookupHandle *clh;
312 struct GNUNET_SERVICE_Client *client = cls;
313 char *credentialptr = credential;
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
317 "Received LOOKUP message\n");
319 utf_in = (const char *) &l_msg[1];
320 GNUNET_STRINGS_utf8_tolower (utf_in, credentialptr);
321 clh = GNUNET_new (struct ClientLookupHandle);
322 GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh);
323 clh->client = client;
324 clh->request_id = l_msg->id;
325 clh->issuer_key = l_msg->issuer_key;
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
328 "Sending LOOKUP_RESULT message with >%u results\n",
331 if (NULL == credential)
333 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
334 "No credential provided\n");
335 send_lookup_response (clh, 0, NULL);
338 clh->lookup_request = GNUNET_GNS_lookup (gns,
340 &l_msg->subject_key, //subject_pkey,
341 GNUNET_GNSRECORD_TYPE_CREDENTIAL,
342 GNUNET_GNS_LO_DEFAULT, //TODO configurable? credential.conf
343 NULL, //shorten_key, always NULL
344 &send_lookup_response,
350 * One of our clients disconnected, clean up after it.
353 * @param client the client that disconnected
356 client_disconnect_cb (void *cls,
357 struct GNUNET_SERVICE_Client *client,
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Client %p disconnected\n",
366 * Add a client to our list of active clients.
369 * @param client client to add
370 * @param mq message queue for @a client
371 * @return this client
374 client_connect_cb (void *cls,
375 struct GNUNET_SERVICE_Client *client,
376 struct GNUNET_MQ_Handle *mq)
378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
379 "Client %p connected\n",
385 * Process Credential requests.
388 * @param server the initialized server
389 * @param c configuration to use
393 const struct GNUNET_CONFIGURATION_Handle *c,
394 struct GNUNET_SERVICE_Handle *handle)
397 gns = GNUNET_GNS_connect (c);
401 _("Failed to connect to GNS\n"));
404 statistics = GNUNET_STATISTICS_create ("credential", c);
405 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
410 * Define "main" method using service macro
414 GNUNET_SERVICE_OPTION_NONE,
417 &client_disconnect_cb,
419 GNUNET_MQ_hd_var_size (lookup,
420 GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP,
421 struct LookupMessage,
423 GNUNET_MQ_handler_end());
425 /* end of gnunet-service-credential.c */