aboutsummaryrefslogtreecommitdiff
path: root/src/credential/gnunet-service-credential.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/credential/gnunet-service-credential.c')
-rw-r--r--src/credential/gnunet-service-credential.c425
1 files changed, 425 insertions, 0 deletions
diff --git a/src/credential/gnunet-service-credential.c b/src/credential/gnunet-service-credential.c
new file mode 100644
index 000000000..de0592637
--- /dev/null
+++ b/src/credential/gnunet-service-credential.c
@@ -0,0 +1,425 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 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 gns/gnunet-service-credential.c
22 * @brief GNU Credential Service (main service)
23 * @author Adnan Husain
24 */
25#include "platform.h"
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"
31
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"
39
40
41
42
43#define GNUNET_CREDENTIAL_MAX_LENGTH 255
44
45/**
46 * DLL for record
47 */
48struct CredentialRecordEntry
49{
50 /**
51 * DLL
52 */
53 struct CredentialRecordEntry *next;
54
55 /**
56 * DLL
57 */
58 struct CredentialRecordEntry *prev;
59
60
61 /**
62 * Payload
63 */
64 struct GNUNET_CREDENTIAL_RecordData record_data;
65};
66
67/**
68 * Handle to a lookup operation from api
69 */
70struct ClientLookupHandle
71{
72
73 /**
74 * We keep these in a DLL.
75 */
76 struct ClientLookupHandle *next;
77
78 /**
79 * We keep these in a DLL.
80 */
81 struct ClientLookupHandle *prev;
82
83 /**
84 * Handle to the requesting client
85 */
86 struct GNUNET_SERVICE_Client *client;
87
88 /**
89 * Handle to GNS lookup
90 */
91 struct GNUNET_GNS_LookupRequest *lookup_request;
92
93 /**
94 * Authority public key
95 */
96 struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
97
98 /**
99 * Credential Chain
100 */
101 struct CredentialRecordEntry *cred_chain_head;
102
103 /**
104 * Credential Chain
105 */
106 struct CredentialRecordEntry *cred_chain_tail;
107
108 /**
109 * request id
110 */
111 uint32_t request_id;
112
113};
114
115
116/**
117 * Head of the DLL.
118 */
119static struct ClientLookupHandle *clh_head;
120
121/**
122 * Tail of the DLL.
123 */
124static struct ClientLookupHandle *clh_tail;
125
126/**
127 * Handle to the statistics service
128 */
129static struct GNUNET_STATISTICS_Handle *statistics;
130
131
132
133/**
134 * Handle to GNS service.
135 */
136static struct GNUNET_GNS_Handle *gns;
137
138/**
139 * Task run during shutdown.
140 *
141 * @param cls unused
142 * @param tc unused
143 */
144static void
145shutdown_task (void *cls)
146{
147 struct ClientLookupHandle *clh;
148
149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
150 "Shutting down!\n");
151 while (NULL != (clh = clh_head))
152 {
153 //CREDENTIAL_resolver_lookup_cancel (clh->lookup);
154 GNUNET_CONTAINER_DLL_remove (clh_head,
155 clh_tail,
156 clh);
157 GNUNET_free (clh);
158 }
159
160
161 if (NULL != statistics)
162 {
163 GNUNET_STATISTICS_destroy (statistics,
164 GNUNET_NO);
165 statistics = NULL;
166 }
167
168}
169
170/**
171 * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP message
172 *
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
176 */
177static int
178check_lookup (void *cls,
179 const struct LookupMessage *l_msg)
180{
181 size_t msg_size;
182 const char* cred;
183
184 msg_size = ntohs (l_msg->header.size);
185 if (msg_size < sizeof (struct LookupMessage))
186 {
187 GNUNET_break (0);
188 return GNUNET_SYSERR;
189 }
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) )
193 {
194 GNUNET_break (0);
195 return GNUNET_SYSERR;
196 }
197 return GNUNET_OK;
198}
199
200
201/**
202 * Reply to client with the result from our lookup.
203 *
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
207 */
208static void
209send_lookup_response (void* cls,
210 uint32_t rd_count,
211 const struct GNUNET_GNSRECORD_Data *rd)
212{
213 struct ClientLookupHandle *clh = cls;
214 size_t len;
215 int i;
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;
221
222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223 "Sending LOOKUP_RESULT message with %u results\n",
224 (unsigned int) rd_count);
225
226 cred_record_count = 0;
227 for (i=0; i < rd_count; i++)
228 {
229 if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
230 continue;
231 cred_record_count++;
232 crd = rd[i].data;
233 /**
234 * TODO: Check for:
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
238 *
239 * In any case:
240 * Append crd to result list of RecordData
241 */
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,
246 cr_entry);
247
248 }
249
250 /**
251 * Get serialized record data size
252 */
253 len = cred_record_count * sizeof (struct GNUNET_CREDENTIAL_RecordData);
254
255 /**
256 * Prepare a lookup result response message for the client
257 */
258 env = GNUNET_MQ_msg_extra (rmsg,
259 len,
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);
264
265 /**
266 * Get serialized record data
267 * Append at the end of rmsg
268 */
269 i = 0;
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)
272 {
273 memcpy (tmp_record,
274 &cr_entry->record_data,
275 sizeof (struct GNUNET_CREDENTIAL_RecordData));
276 tmp_record++;
277 }
278 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->client),
279 env);
280
281 GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh);
282
283 /**
284 * TODO:
285 * - Free DLL
286 * - Refactor into cleanup_handle() function for this
287 */
288 GNUNET_free (clh);
289
290 GNUNET_STATISTICS_update (statistics,
291 "Completed lookups", 1,
292 GNUNET_NO);
293 GNUNET_STATISTICS_update (statistics,
294 "Records resolved",
295 rd_count,
296 GNUNET_NO);
297}
298
299/**
300 * Handle lookup requests from client
301 *
302 * @param cls the closure
303 * @param client the client
304 * @param message the message
305 */
306static void
307handle_lookup (void *cls,
308 const struct LookupMessage *l_msg)
309{
310 char credential[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
311 struct ClientLookupHandle *clh;
312 struct GNUNET_SERVICE_Client *client = cls;
313 char *credentialptr = credential;
314 const char *utf_in;
315
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
317 "Received LOOKUP message\n");
318
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;
326
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
328 "Sending LOOKUP_RESULT message with >%u results\n",
329 0);
330
331 if (NULL == credential)
332 {
333 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
334 "No credential provided\n");
335 send_lookup_response (clh, 0, NULL);
336 return;
337 }
338 clh->lookup_request = GNUNET_GNS_lookup (gns,
339 credential,
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,
345 clh);
346}
347
348
349/**
350 * One of our clients disconnected, clean up after it.
351 *
352 * @param cls NULL
353 * @param client the client that disconnected
354 */
355static void
356client_disconnect_cb (void *cls,
357 struct GNUNET_SERVICE_Client *client,
358 void *app_ctx)
359{
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Client %p disconnected\n",
362 client);
363}
364
365/**
366 * Add a client to our list of active clients.
367 *
368 * @param cls NULL
369 * @param client client to add
370 * @param mq message queue for @a client
371 * @return this client
372 */
373static void *
374client_connect_cb (void *cls,
375 struct GNUNET_SERVICE_Client *client,
376 struct GNUNET_MQ_Handle *mq)
377{
378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
379 "Client %p connected\n",
380 client);
381 return client;
382}
383
384/**
385 * Process Credential requests.
386 *
387 * @param cls closure
388 * @param server the initialized server
389 * @param c configuration to use
390 */
391static void
392run (void *cls,
393 const struct GNUNET_CONFIGURATION_Handle *c,
394 struct GNUNET_SERVICE_Handle *handle)
395{
396
397 gns = GNUNET_GNS_connect (c);
398 if (NULL == gns)
399 {
400 fprintf (stderr,
401 _("Failed to connect to GNS\n"));
402 }
403
404 statistics = GNUNET_STATISTICS_create ("credential", c);
405 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
406}
407
408
409/**
410 * Define "main" method using service macro
411 */
412GNUNET_SERVICE_MAIN
413("credential",
414 GNUNET_SERVICE_OPTION_NONE,
415 &run,
416 &client_connect_cb,
417 &client_disconnect_cb,
418 NULL,
419 GNUNET_MQ_hd_var_size (lookup,
420 GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP,
421 struct LookupMessage,
422 NULL),
423 GNUNET_MQ_handler_end());
424
425/* end of gnunet-service-credential.c */