From 4e6cb01843318385cfad41aec4cde5791f51cde2 Mon Sep 17 00:00:00 2001 From: Phil Date: Mon, 25 Jun 2018 00:17:06 +0200 Subject: Identity+GNS Rest changed and fixed --- src/identity/plugin_rest_identity.c | 837 ++++++++++++++++-------------------- 1 file changed, 382 insertions(+), 455 deletions(-) (limited to 'src/identity/plugin_rest_identity.c') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index fd6562f1d..8d525b950 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -1,26 +1,27 @@ /* - This file is part of GNUnet. - Copyright (C) 2012-2015 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ + This file is part of GNUnet. + Copyright (C) 2012-2015 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. + */ /** * @author Martin Schanzenbach * @author Philippe Buschmann * @file identity/plugin_rest_identity.c - * @brief GNUnet Namestore REST plugin - * + * @brief GNUnet Identity REST plugin */ #include "platform.h" @@ -29,56 +30,34 @@ #include "gnunet_rest_lib.h" #include "microhttpd.h" #include -#include "gnunet_signatures.h" -/** - * REST root namespace - */ #define GNUNET_REST_API_NS_IDENTITY "/identity" /** - * State while collecting all egos - */ -#define ID_REST_STATE_INIT 0 - -/** - * Done collecting egos - */ -#define ID_REST_STATE_POST_INIT 1 - -/** - * Resource type - */ -#define GNUNET_REST_JSON_IDENTITY_EGO "ego" - -/** - * Name attribute - */ -#define GNUNET_REST_JSON_IDENTITY_NAME "name" - -/** - * Attribute to rename "name" TODO we changed id to the pubkey - * so this can be unified with "name" + * Parameter names */ -#define GNUNET_REST_JSON_IDENTITY_NEWNAME "newname" - -/** - * URL parameter to change the subsytem for ego - */ -#define GNUNET_REST_JSON_IDENTITY_SUBSYSTEM "subsystem" - +#define GNUNET_REST_PARAM_PUBKEY "pubkey" +#define GNUNET_REST_PARAM_SUBSYSTEM "subsystem" +#define GNUNET_REST_PARAM_NAME "name" +#define GNUNET_REST_PARAM_NEWNAME "newname" /** * Error messages */ +#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" #define GNUNET_REST_ERROR_NO_DATA "No data" #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" /** - * GNUid token lifetime + * State while collecting all egos + */ +#define ID_REST_STATE_INIT 0 + +/** + * Done collecting egos */ -#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 +#define ID_REST_STATE_POST_INIT 1 /** * The configuration handle @@ -129,28 +108,37 @@ struct EgoEntry struct GNUNET_IDENTITY_Ego *ego; }; - struct RequestHandle { /** - * Ego list + * The data from the REST request */ - struct EgoEntry *ego_head; + const char* data; /** - * Ego list + * The name to look up */ - struct EgoEntry *ego_tail; + char *name; /** - * Handle to the rest connection + * the length of the REST data */ - struct GNUNET_REST_RequestHandle *conndata_handle; + size_t data_size; /** - * response code + * Requested Subsystem */ - int response_code; + char *subsystem; + + /** + * Ego list + */ + struct EgoEntry *ego_head; + + /** + * Ego list + */ + struct EgoEntry *ego_tail; /** * The processing state @@ -158,7 +146,7 @@ struct RequestHandle int state; /** - * Handle to GNS service. + * Handle to Identity service. */ struct GNUNET_IDENTITY_Handle *identity_handle; @@ -167,6 +155,11 @@ struct RequestHandle */ struct GNUNET_IDENTITY_Operation *op; + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + /** * Desired timeout for the lookup (default is no timeout). */ @@ -175,7 +168,7 @@ struct RequestHandle /** * ID of a task associated with the resolution process. */ - struct GNUNET_SCHEDULER_Task * timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * The plugin result processor @@ -187,44 +180,23 @@ struct RequestHandle */ void *proc_cls; - /** - * The name to look up - */ - char *name; - - /** - * The subsystem set from REST - */ - char *subsys; - /** * The url */ char *url; /** - * The data from the REST request - */ - const char* data; - - /** - * the length of the REST data - */ - size_t data_size; - - /** - * HTTP method + * Error response message */ - const char* method; + char *emsg; /** - * Error response message + * Reponse code */ - char *emsg; + int response_code; }; - /** * Cleanup lookup handle * @param handle Handle to clean up @@ -234,35 +206,37 @@ cleanup_handle (struct RequestHandle *handle) { struct EgoEntry *ego_entry; struct EgoEntry *ego_tmp; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->name) - GNUNET_free (handle->name); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); if (NULL != handle->timeout_task) { GNUNET_SCHEDULER_cancel (handle->timeout_task); handle->timeout_task = NULL; } - if (NULL != handle->identity_handle) - GNUNET_IDENTITY_disconnect (handle->identity_handle); - if (NULL != handle->subsys) - GNUNET_free (handle->subsys); + + if (NULL != handle->subsystem) + GNUNET_free(handle->subsystem); if (NULL != handle->url) - GNUNET_free (handle->url); + GNUNET_free(handle->url); if (NULL != handle->emsg) - GNUNET_free (handle->emsg); + GNUNET_free(handle->emsg); + if (NULL != handle->name) + GNUNET_free (handle->name); + if (NULL != handle->identity_handle) + GNUNET_IDENTITY_disconnect (handle->identity_handle); + for (ego_entry = handle->ego_head; - NULL != ego_entry;) + NULL != ego_entry;) { ego_tmp = ego_entry; ego_entry = ego_entry->next; - GNUNET_free (ego_tmp->identifier); - GNUNET_free (ego_tmp->keystring); - GNUNET_free (ego_tmp); + GNUNET_free(ego_tmp->identifier); + GNUNET_free(ego_tmp->keystring); + GNUNET_free(ego_tmp); } - GNUNET_free (handle); -} + GNUNET_free(handle); +} /** * Task run on errors. Reports an error and cleans up everything. @@ -277,10 +251,12 @@ do_error (void *cls) char *json_error; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - handle->response_code = MHD_HTTP_OK; + + if (0 == handle->response_code) + handle->response_code = MHD_HTTP_OK; resp = GNUNET_REST_create_response (json_error); handle->proc (handle->proc_cls, resp, handle->response_code); @@ -288,9 +264,8 @@ do_error (void *cls) GNUNET_free(json_error); } - /** - * Callback for IDENTITY_get() + * Callback for GET Request with subsystem * * @param cls the RequestHandle * @param ego the Ego found @@ -298,173 +273,153 @@ do_error (void *cls) * @param name the id of the ego */ static void -get_ego_for_subsys (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) +ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, + const char *name) { struct RequestHandle *handle = cls; - struct EgoEntry *ego_entry; struct MHD_Response *resp; + struct GNUNET_CRYPTO_EcdsaPublicKey public_key; json_t *json_root; - json_t *json_ego; - json_t *name_json; char *result_str; - size_t index; - - json_root = json_array(); + char *public_key_string; - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + if(NULL == ego) { - if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) ) - continue; - if (NULL == name) - continue; - - json_ego = json_object(); - name_json = json_string (ego_entry->identifier); - json_object_set_new(json_ego, GNUNET_REST_JSON_IDENTITY_EGO, name_json); - json_array_append(json_root, json_ego); - - break; - } - - if (0 == json_array_size(json_root)) - { - json_decref(json_root); - handle->emsg = GNUNET_strdup("No identity matches results!"); + handle->emsg = GNUNET_strdup("No identity found for subsystem"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - result_str = json_dumps(json_root, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + GNUNET_IDENTITY_ego_get_public_key(ego,&public_key); + public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key); + + // create json with subsystem identity + json_root = json_object (); + json_object_set_new (json_root, GNUNET_REST_PARAM_PUBKEY, json_string(public_key_string)); + json_object_set_new (json_root, GNUNET_REST_PARAM_NAME, json_string(name)); + + result_str = json_dumps (json_root, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - json_array_foreach(json_root, index, json_ego ) - { - json_decref(json_ego); - } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result_str); + GNUNET_free(result_str); + GNUNET_free(public_key_string); cleanup_handle (handle); } - /** - * Create a response with requested ego(s) + * Handle identity GET request * - * @param con the Rest handle - * @param url the requested url - * @param cls the request handle + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ -static void -ego_info_response (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { - const char *egoname; - char *result_str; - char *subsys_val; - char *keystring; struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct GNUNET_HashCode key; struct MHD_Response *resp; + char *keystring; + const char *egoname; json_t *json_root; json_t *json_ego; - json_t *name_str; + char *result_str; size_t index; - if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) - { - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); - cleanup_handle (handle); + //if subsystem + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM, + strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) + { + handle->subsystem = GNUNET_strdup( + GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key)); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", + handle->subsystem); + + handle->op = GNUNET_IDENTITY_get (handle->identity_handle, + handle->subsystem, &ego_get_for_subsystem, + handle); + if (NULL == handle->op) + { + handle->emsg = GNUNET_strdup("No identity found for subsystem"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } return; } egoname = NULL; keystring = NULL; - if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url)) + + //if only one identity requested + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, + strlen (GNUNET_REST_PARAM_PUBKEY), &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) { - keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1]; - //Return all egos + keystring = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, &key); + for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { - if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) ) - continue; + if ((NULL != keystring) + && (0 != strcmp (keystring, ego_entry->keystring))) + continue; egoname = ego_entry->identifier; } } - if ( NULL == egoname ) { - GNUNET_CRYPTO_hash (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM, - strlen (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, - &key) ) - { - subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, - &key); - if (NULL != subsys_val) - { - GNUNET_asprintf (&handle->subsys, "%s", subsys_val); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val); - handle->op = GNUNET_IDENTITY_get (handle->identity_handle, - handle->subsys, - &get_ego_for_subsys, - handle); - return; - } - } - } - - json_root = json_array(); - - //Return all egos + json_root = json_array (); + //Return ego/egos for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { - if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) - continue; - - json_ego = json_object(); - - json_object_set_new( json_ego, "id", json_string (ego_entry->keystring)); - json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSON_IDENTITY_EGO)); - name_str = json_string (ego_entry->identifier); - json_object_set_new( json_ego, "name", name_str); + //if only one ego requested + if ((NULL != egoname)){ + if(0 != strcmp (egoname, ego_entry->identifier)){ + continue; + } + } - json_array_append( json_root, json_ego ); + json_ego = json_object (); + json_object_set_new (json_ego, + GNUNET_REST_PARAM_PUBKEY, + json_string (ego_entry->keystring)); + json_object_set_new (json_ego, + GNUNET_REST_PARAM_NAME, + json_string (ego_entry->identifier)); + json_array_append (json_root, json_ego); } - if ((size_t)0 == json_array_size(json_root)) + if ((size_t) 0 == json_array_size (json_root)) { json_decref (json_root); - handle->emsg = GNUNET_strdup ("No identities found!"); + handle->emsg = GNUNET_strdup("No identities found!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - result_str = json_dumps(json_root, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + result_str = json_dumps (json_root, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); //delete json_objects in json_array with macro json_array_foreach(json_root, index, json_ego ) { - json_decref(json_ego); + json_decref (json_ego); } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result_str); + GNUNET_free(result_str); cleanup_handle (handle); } @@ -483,7 +438,7 @@ do_finished (void *cls, const char *emsg) handle->op = NULL; if (NULL != emsg) { - handle->emsg = GNUNET_strdup (emsg); + handle->emsg = GNUNET_strdup(emsg); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -493,288 +448,280 @@ do_finished (void *cls, const char *emsg) } /** - * Create a new ego + * Handle identity PUT request * - * @param con rest handle - * @param url url - * @param cls request handle + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ -static void -ego_create_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; + struct EgoEntry *ego_entry_tmp; struct MHD_Response *resp; - json_t *egoname_json; + json_t *subsys_json; + json_t *name_json; + json_t *key_json; json_t *data_js; json_error_t err; - const char* egoname; - char term_data[handle->data_size+1]; - - if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) - { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } + const char *keystring; + const char *subsys; + const char *newname; + char term_data[handle->data_size + 1]; + int ego_exists = GNUNET_NO; + //if no data if (0 >= handle->data_size) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + //if not json term_data[handle->data_size] = '\0'; - GNUNET_memcpy (term_data, handle->data, handle->data_size); - data_js = json_loads (term_data, - JSON_DECODE_ANY, - &err); - - + GNUNET_memcpy(term_data, handle->data, handle->data_size); + data_js = json_loads (term_data,JSON_DECODE_ANY,&err); if (NULL == data_js) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - //instead of parse if (!json_is_object(data_js)) { - json_decref(data_js); - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + json_decref (data_js); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - if (1 != json_object_size (data_js)) + //json must contain pubkey and (subsystem or name) + if (2 != json_object_size (data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup("Provided resource count invalid"); + handle->emsg = GNUNET_strdup("Resource amount invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NAME); - if (!json_is_string (egoname_json)) + key_json = json_object_get (data_js, GNUNET_REST_PARAM_PUBKEY); + if ((NULL == key_json) || !json_is_string(key_json)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); + handle->emsg = GNUNET_strdup("Missing element pubkey"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname = json_string_value (egoname_json); - if(0 >= strlen(egoname)) + keystring = json_string_value (key_json); + + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 != strcasecmp (keystring, ego_entry->keystring)) + continue; + ego_exists = GNUNET_YES; + break; + } + + if (GNUNET_NO == ego_exists) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + cleanup_handle (handle); return; } - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + //This is a rename + name_json = json_object_get (data_js, GNUNET_REST_PARAM_NEWNAME); + if ((NULL != name_json) && json_is_string(name_json)) { - if (0 == strcasecmp (egoname, ego_entry->identifier)) + newname = json_string_value (name_json); + if (0 >= strlen (newname)) { json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + for (ego_entry_tmp = handle->ego_head; + NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next) + { + if (0 == strcasecmp (newname, ego_entry_tmp->identifier) + && 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) + { + //Ego with same name not allowed + json_decref (data_js); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + cleanup_handle (handle); + return; + } + } + handle->response_code = MHD_HTTP_NO_CONTENT; + handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, + ego_entry->identifier, newname, + &do_finished, handle); + json_decref (data_js); + return; + } + + //Set subsystem + subsys_json = json_object_get (data_js, GNUNET_REST_PARAM_SUBSYSTEM); + if ((NULL != subsys_json) && json_is_string(subsys_json)) + { + subsys = json_string_value (subsys_json); + if (0 >= strlen (subsys)) + { + json_decref (data_js); + handle->emsg = GNUNET_strdup("Invalid subsystem name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_asprintf (&handle->subsystem, "%s", subsys); + json_decref (data_js); + handle->response_code = MHD_HTTP_NO_CONTENT; + handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsystem, + ego_entry->ego, &do_finished, handle); + return; } - GNUNET_asprintf (&handle->name, "%s", egoname); json_decref (data_js); - handle->response_code = MHD_HTTP_CREATED; - handle->op = GNUNET_IDENTITY_create (handle->identity_handle, - handle->name, - &do_finished, - handle); + handle->emsg = GNUNET_strdup("Subsystem not provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); } - /** - * Handle ego edit request + * Handle identity POST request * - * @param con rest connection handle - * @param url the url that is requested + * @param con_handle the connection handle + * @param url the url * @param cls the RequestHandle */ -static void -ego_edit_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; - struct EgoEntry *ego_entry_tmp; struct MHD_Response *resp; - json_t *subsys_json; - json_t *name_json; + json_t *egoname_json; json_t *data_js; json_error_t err; - const char *keystring; - const char *subsys; - const char *newname; - char term_data[handle->data_size+1]; - int ego_exists = GNUNET_NO; + const char* egoname; + char term_data[handle->data_size + 1]; - if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) + if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_RESOURCE_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; - - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) - { - if (0 != strcasecmp (keystring, ego_entry->keystring)) - continue; - ego_exists = GNUNET_YES; - break; - } - - if (GNUNET_NO == ego_exists) - { - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - if (0 >= handle->data_size) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - term_data[handle->data_size] = '\0'; - GNUNET_memcpy (term_data, handle->data, handle->data_size); + GNUNET_memcpy(term_data, handle->data, handle->data_size); data_js = json_loads (term_data, - JSON_DECODE_ANY, - &err); + JSON_DECODE_ANY, + &err); + if (NULL == data_js) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + //instead of parse if (!json_is_object(data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (1 != json_object_size(data_js)) + if (1 != json_object_size (data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("Resource amount invalid"); + handle->emsg = GNUNET_strdup("Provided resource count invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - //This is a rename - name_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NEWNAME); - if ((NULL != name_json) && json_is_string (name_json)) + egoname_json = json_object_get (data_js, GNUNET_REST_PARAM_NAME); + if (!json_is_string(egoname_json)) { - newname = json_string_value (name_json); - if(0 >= strlen(newname)) - { - json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - for (ego_entry_tmp = handle->ego_head; - NULL != ego_entry_tmp; - ego_entry_tmp = ego_entry_tmp->next) - { - if (0 == strcasecmp (newname, ego_entry_tmp->identifier) && - 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) - { - //Ego with same name not allowed - json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); - return; - } - } - handle->response_code = MHD_HTTP_NO_CONTENT; - handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, - ego_entry->identifier, - newname, - &do_finished, - handle); json_decref (data_js); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - //Set subsystem - subsys_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_SUBSYSTEM); - if ( (NULL != subsys_json) && json_is_string (subsys_json)) + egoname = json_string_value (egoname_json); + if (0 >= strlen (egoname)) { - subsys = json_string_value (subsys_json); - if(0 >= strlen(subsys)) + json_decref (data_js); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 == strcasecmp (egoname, ego_entry->identifier)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + cleanup_handle (handle); return; } - GNUNET_asprintf (&handle->subsys, "%s", subsys); - json_decref (data_js); - handle->response_code = MHD_HTTP_NO_CONTENT; - handle->op = GNUNET_IDENTITY_set (handle->identity_handle, - handle->subsys, - ego_entry->ego, - &do_finished, - handle); - return; } + GNUNET_asprintf (&handle->name, "%s", egoname); json_decref (data_js); - handle->emsg = GNUNET_strdup ("Subsystem not provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + handle->response_code = MHD_HTTP_CREATED; + handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, + &do_finished, handle); } /** - * Handle ego delete request + * Handle identity DELETE request * * @param con_handle the connection handle * @param url the url * @param cls the RequestHandle */ void -ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) +ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { const char *keystring; struct EgoEntry *ego_entry; + struct GNUNET_HashCode key; struct MHD_Response *resp; struct RequestHandle *handle = cls; int ego_exists = GNUNET_NO; - if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) + //if only one identity requested + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, + strlen (GNUNET_REST_PARAM_PUBKEY), &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); + handle->emsg = GNUNET_strdup("Missing parameter pubkey"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; + keystring = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map,&key); for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { if (0 != strcasecmp (keystring, ego_entry->keystring)) continue; @@ -790,13 +737,11 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, } handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, - ego_entry->identifier, - &do_finished, - handle); + ego_entry->identifier, &do_finished, + handle); } - /** * Respond to OPTIONS request * @@ -805,18 +750,15 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, * @param cls the RequestHandle */ static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) +options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct MHD_Response *resp; struct RequestHandle *handle = cls; //For now, independent of path return all options resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); + MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); cleanup_handle (handle); return; @@ -832,18 +774,17 @@ init_cont (struct RequestHandle *handle) { struct GNUNET_REST_RequestHandlerError err; static const struct GNUNET_REST_RequestHandler handlers[] = { - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response}, - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont}, - {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont}, - {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont}, - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont}, - GNUNET_REST_HANDLER_END + { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get }, + { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit }, + { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create }, + { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete }, + { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont }, + GNUNET_REST_HANDLER_END }; - if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, - handlers, - &err, - handle)) + if (GNUNET_NO + == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, + handle)) { handle->response_code = err.error_code; GNUNET_SCHEDULER_add_now (&do_error, handle); @@ -884,10 +825,8 @@ init_cont (struct RequestHandle *handle) * must thus no longer be used */ static void -list_ego (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *identifier) +init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, + const char *identifier) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; @@ -899,16 +838,16 @@ list_ego (void *cls, init_cont (handle); return; } - if (ID_REST_STATE_INIT == handle->state) { - ego_entry = GNUNET_new (struct EgoEntry); + if (ID_REST_STATE_INIT == handle->state) + { + ego_entry = GNUNET_new(struct EgoEntry); GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = - GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); ego_entry->ego = ego; GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); - GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, + ego_entry); } - } /** @@ -923,39 +862,30 @@ list_ego (void *cls, * @return GNUNET_OK if request accepted */ static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) +rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, void *proc_cls) { - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - - + struct RequestHandle *handle = GNUNET_new(struct RequestHandle); + handle->response_code = 0; handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->response_code = MHD_HTTP_OK; handle->proc_cls = proc_cls; handle->proc = proc; - handle->state = ID_REST_STATE_INIT; - handle->conndata_handle = conndata_handle; - handle->data = conndata_handle->data; - handle->data_size = conndata_handle->data_size; - handle->method = conndata_handle->method; - GNUNET_asprintf (&handle->url, "%s", conndata_handle->url); - if (handle->url[strlen (handle->url)-1] == '/') - handle->url[strlen (handle->url)-1] = '\0'; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting...\n"); - handle->identity_handle = GNUNET_IDENTITY_connect (cfg, - &list_ego, - handle); - handle->timeout_task = - GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, - handle); - - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected\n"); + handle->rest_handle = rest_handle; + handle->data = rest_handle->data; + handle->data_size = rest_handle->data_size; + + handle->url = GNUNET_strdup(rest_handle->url); + if (handle->url[strlen (handle->url) - 1] == '/') + handle->url[strlen (handle->url) - 1] = '\0'; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); + + handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle); + + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, handle); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); } /** @@ -972,27 +902,24 @@ libgnunet_plugin_rest_identity_init (void *cls) cfg = cls; if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof(struct Plugin)); plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); + api = GNUNET_new(struct GNUNET_REST_Plugin); api->cls = &plugin; api->name = GNUNET_REST_API_NS_IDENTITY; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Identity REST API initialized\n")); + api->process_request = &rest_process_request; + GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n")); return api; } - /** * Exit point from the plugin. * @@ -1004,13 +931,13 @@ libgnunet_plugin_rest_identity_done (void *cls) { struct GNUNET_REST_Plugin *api = cls; struct Plugin *plugin = api->cls; - plugin->cfg = NULL; - GNUNET_free_non_null (allow_methods); - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Identity REST plugin is finished\n"); + + GNUNET_free_non_null(allow_methods); + GNUNET_free(api); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n"); return NULL; } -/* end of plugin_rest_gns.c */ +/* end of plugin_rest_identity.c */ + -- cgit v1.2.3