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 0000000000..de05926375 --- /dev/null +++ b/src/credential/gnunet-service-credential.c @@ -0,0 +1,425 @@ +/* + This file is part of GNUnet. + Copyright (C) 2011-2013 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +/** + * @file gns/gnunet-service-credential.c + * @brief GNU Credential Service (main service) + * @author Adnan Husain + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_credential_service.h" +#include "gnunet_statistics_service.h" +#include "credential.h" +#include "gnunet_protocols.h" + +// For Looking up GNS request +#include <gnunet_dnsparser_lib.h> +#include <gnunet_identity_service.h> +#include <gnunet_gnsrecord_lib.h> +#include <gnunet_namestore_service.h> +#include <gnunet_gns_service.h> +#include "gnunet_gns_service.h" + + + + +#define GNUNET_CREDENTIAL_MAX_LENGTH 255 + +/** + * DLL for record + */ +struct CredentialRecordEntry +{ + /** + * DLL + */ + struct CredentialRecordEntry *next; + + /** + * DLL + */ + struct CredentialRecordEntry *prev; + + + /** + * Payload + */ + struct GNUNET_CREDENTIAL_RecordData record_data; +}; + +/** + * Handle to a lookup operation from api + */ +struct ClientLookupHandle +{ + + /** + * We keep these in a DLL. + */ + struct ClientLookupHandle *next; + + /** + * We keep these in a DLL. + */ + struct ClientLookupHandle *prev; + + /** + * Handle to the requesting client + */ + struct GNUNET_SERVICE_Client *client; + + /** + * Handle to GNS lookup + */ + struct GNUNET_GNS_LookupRequest *lookup_request; + + /** + * Authority public key + */ + struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key; + + /** + * Credential Chain + */ + struct CredentialRecordEntry *cred_chain_head; + + /** + * Credential Chain + */ + struct CredentialRecordEntry *cred_chain_tail; + + /** + * request id + */ + uint32_t request_id; + +}; + + +/** + * Head of the DLL. + */ +static struct ClientLookupHandle *clh_head; + +/** + * Tail of the DLL. + */ +static struct ClientLookupHandle *clh_tail; + +/** + * Handle to the statistics service + */ +static struct GNUNET_STATISTICS_Handle *statistics; + + + +/** + * Handle to GNS service. + */ +static struct GNUNET_GNS_Handle *gns; + +/** + * Task run during shutdown. + * + * @param cls unused + * @param tc unused + */ +static void +shutdown_task (void *cls) +{ + struct ClientLookupHandle *clh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Shutting down!\n"); + while (NULL != (clh = clh_head)) + { + //CREDENTIAL_resolver_lookup_cancel (clh->lookup); + GNUNET_CONTAINER_DLL_remove (clh_head, + clh_tail, + clh); + GNUNET_free (clh); + } + + + if (NULL != statistics) + { + GNUNET_STATISTICS_destroy (statistics, + GNUNET_NO); + statistics = NULL; + } + +} + +/** + * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP message + * + * @param cls client sending the message + * @param l_msg message of type `struct LookupMessage` + * @return #GNUNET_OK if @a l_msg is well-formed + */ +static int +check_lookup (void *cls, + const struct LookupMessage *l_msg) +{ + size_t msg_size; + const char* cred; + + msg_size = ntohs (l_msg->header.size); + if (msg_size < sizeof (struct LookupMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + cred = (const char *) &l_msg[1]; + if ( ('\0' != cred[l_msg->header.size - sizeof (struct LookupMessage) - 1]) || + (strlen (cred) > GNUNET_CREDENTIAL_MAX_LENGTH) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Reply to client with the result from our lookup. + * + * @param cls the closure (our client lookup handle) + * @param rd_count the number of records in @a rd + * @param rd the record data + */ +static void +send_lookup_response (void* cls, + uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct ClientLookupHandle *clh = cls; + size_t len; + int i; + int cred_record_count; + struct GNUNET_MQ_Envelope *env; + struct LookupResultMessage *rmsg; + const struct GNUNET_CREDENTIAL_RecordData *crd; + struct CredentialRecordEntry *cr_entry; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending LOOKUP_RESULT message with %u results\n", + (unsigned int) rd_count); + + cred_record_count = 0; + for (i=0; i < rd_count; i++) + { + if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type) + continue; + cred_record_count++; + crd = rd[i].data; + /** + * TODO: Check for: + * - First time we come here subject must be subject prvided by client + * - After that is has to be the prev issuer + * - Terminate condition: issuer is clh->authority_key + * + * In any case: + * Append crd to result list of RecordData + */ + cr_entry = GNUNET_new (struct CredentialRecordEntry); + cr_entry->record_data = *crd; + GNUNET_CONTAINER_DLL_insert_tail (clh->cred_chain_head, + clh->cred_chain_tail, + cr_entry); + + } + + /** + * Get serialized record data size + */ + len = cred_record_count * sizeof (struct GNUNET_CREDENTIAL_RecordData); + + /** + * Prepare a lookup result response message for the client + */ + env = GNUNET_MQ_msg_extra (rmsg, + len, + GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP_RESULT); + //Assign id so that client can find associated request + rmsg->id = clh->request_id; + rmsg->cd_count = htonl (cred_record_count); + + /** + * Get serialized record data + * Append at the end of rmsg + */ + i = 0; + struct GNUNET_CREDENTIAL_RecordData *tmp_record = (struct GNUNET_CREDENTIAL_RecordData*) &rmsg[1]; + for (cr_entry = clh->cred_chain_head; NULL != cr_entry; cr_entry = cr_entry->next) + { + memcpy (tmp_record, + &cr_entry->record_data, + sizeof (struct GNUNET_CREDENTIAL_RecordData)); + tmp_record++; + } + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->client), + env); + + GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); + + /** + * TODO: + * - Free DLL + * - Refactor into cleanup_handle() function for this + */ + GNUNET_free (clh); + + GNUNET_STATISTICS_update (statistics, + "Completed lookups", 1, + GNUNET_NO); + GNUNET_STATISTICS_update (statistics, + "Records resolved", + rd_count, + GNUNET_NO); +} + +/** + * Handle lookup requests from client + * + * @param cls the closure + * @param client the client + * @param message the message + */ +static void +handle_lookup (void *cls, + const struct LookupMessage *l_msg) +{ + char credential[GNUNET_CREDENTIAL_MAX_LENGTH + 1]; + struct ClientLookupHandle *clh; + struct GNUNET_SERVICE_Client *client = cls; + char *credentialptr = credential; + const char *utf_in; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received LOOKUP message\n"); + + utf_in = (const char *) &l_msg[1]; + GNUNET_STRINGS_utf8_tolower (utf_in, credentialptr); + clh = GNUNET_new (struct ClientLookupHandle); + GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh); + clh->client = client; + clh->request_id = l_msg->id; + clh->issuer_key = l_msg->issuer_key; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending LOOKUP_RESULT message with >%u results\n", + 0); + + if (NULL == credential) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No credential provided\n"); + send_lookup_response (clh, 0, NULL); + return; + } + clh->lookup_request = GNUNET_GNS_lookup (gns, + credential, + &l_msg->subject_key, //subject_pkey, + GNUNET_GNSRECORD_TYPE_CREDENTIAL, + GNUNET_GNS_LO_DEFAULT, //TODO configurable? credential.conf + NULL, //shorten_key, always NULL + &send_lookup_response, + clh); +} + + +/** + * One of our clients disconnected, clean up after it. + * + * @param cls NULL + * @param client the client that disconnected + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p disconnected\n", + client); +} + +/** + * Add a client to our list of active clients. + * + * @param cls NULL + * @param client client to add + * @param mq message queue for @a client + * @return this client + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p connected\n", + client); + return client; +} + +/** + * Process Credential requests. + * + * @param cls closure + * @param server the initialized server + * @param c configuration to use + */ +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *handle) +{ + + gns = GNUNET_GNS_connect (c); + if (NULL == gns) + { + fprintf (stderr, + _("Failed to connect to GNS\n")); + } + + statistics = GNUNET_STATISTICS_create ("credential", c); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); +} + + +/** + * Define "main" method using service macro + */ +GNUNET_SERVICE_MAIN +("credential", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (lookup, + GNUNET_MESSAGE_TYPE_CREDENTIAL_LOOKUP, + struct LookupMessage, + NULL), + GNUNET_MQ_handler_end()); + +/* end of gnunet-service-credential.c */ |