diff options
Diffstat (limited to 'src/credential/gnunet-service-credential.c')
-rw-r--r-- | src/credential/gnunet-service-credential.c | 425 |
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 | */ | ||
48 | struct 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 | */ | ||
70 | struct 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 | */ | ||
119 | static struct ClientLookupHandle *clh_head; | ||
120 | |||
121 | /** | ||
122 | * Tail of the DLL. | ||
123 | */ | ||
124 | static struct ClientLookupHandle *clh_tail; | ||
125 | |||
126 | /** | ||
127 | * Handle to the statistics service | ||
128 | */ | ||
129 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
130 | |||
131 | |||
132 | |||
133 | /** | ||
134 | * Handle to GNS service. | ||
135 | */ | ||
136 | static struct GNUNET_GNS_Handle *gns; | ||
137 | |||
138 | /** | ||
139 | * Task run during shutdown. | ||
140 | * | ||
141 | * @param cls unused | ||
142 | * @param tc unused | ||
143 | */ | ||
144 | static void | ||
145 | shutdown_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 | */ | ||
177 | static int | ||
178 | check_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 | */ | ||
208 | static void | ||
209 | send_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 | */ | ||
306 | static void | ||
307 | handle_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 | */ | ||
355 | static void | ||
356 | client_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 | */ | ||
373 | static void * | ||
374 | client_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 | */ | ||
391 | static void | ||
392 | run (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 | */ | ||
412 | GNUNET_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 */ | ||