diff options
Diffstat (limited to 'src/authorization/anastasis_authorization_plugin_file.c')
-rw-r--r-- | src/authorization/anastasis_authorization_plugin_file.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/src/authorization/anastasis_authorization_plugin_file.c b/src/authorization/anastasis_authorization_plugin_file.c new file mode 100644 index 0000000..210ade7 --- /dev/null +++ b/src/authorization/anastasis_authorization_plugin_file.c @@ -0,0 +1,302 @@ +/* + This file is part of Anastasis + Copyright (C) 2019 Taler Systems SA + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis 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 + Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file include/anastasis_authorization_plugin_file.c + * @brief authorization plugin file based for testing + * @author Dominik Meister + */ +#include "platform.h" +#include "anastasis_authorization_plugin.h" +#include <taler/taler_mhd_lib.h> + + +/** + * Saves the state of a authorization process + */ +struct ANASTASIS_AUTHORIZATION_State +{ + /** + * UUID of the challenge which is authorised + */ + struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid; + + /** + * Code which is sent to the user (here saved into a file) + */ + uint64_t code; + + /** + * holds the truth information + */ + char *filename; + + /** + * closure + */ + void *cls; +}; + + +/** + * Validate @a data is a well-formed input into the challenge method, + * i.e. @a data is a well-formed phone number for sending an SMS, or + * a well-formed e-mail address for sending an e-mail. Not expected to + * check that the phone number or e-mail account actually exists. + * + * To be possibly used before issuing a 402 payment required to the client. + * + * @param cls closure + * @param connection HTTP client request (for queuing response) + * @param truth_mime mime type of @e data + * @param data input to validate (i.e. is it a valid phone number, etc.) + * @param data_length number of bytes in @a data + * @return #GNUNET_OK if @a data is valid, + * #GNUNET_NO if @a data is invalid and a reply was successfully queued on @a connection + * #GNUNET_SYSERR if @a data invalid but we failed to queue a reply on @a connection + */ +static enum GNUNET_GenericReturnValue +file_validate (void *cls, + struct MHD_Connection *connection, + const char *truth_mime, + const char *data, + size_t data_length) +{ + char *filename; + bool flag; + + if (NULL == data) + return GNUNET_NO; + filename = GNUNET_STRINGS_data_to_string_alloc (data, + data_length); + flag = false; + for (size_t i = 0; i<strlen (filename); i++) + { + if ( (filename[i] == ' ') || + (filename[i] == '/') ) + { + flag = true; + break; + } + } + if (flag) + return GNUNET_NO; + GNUNET_free (filename); + return GNUNET_OK; +} + + +/** + * Begin issuing authentication challenge to user based on @a data. + * I.e. start to send SMS or e-mail or launch video identification. + * + * @param cls closure + * @param trigger function to call when we made progress + * @param trigger_cls closure for @a trigger + * @param truth_uuid Identifier of the challenge, to be (if possible) included in the + * interaction with the user + * @param code secret code that the user has to provide back to satisfy the challenge in + * the main anastasis protocol + * @param data input to validate (i.e. is it a valid phone number, etc.) + * @return state to track progress on the authorization operation, NULL on failure + */ +static struct ANASTASIS_AUTHORIZATION_State * +file_start (void *cls, + GNUNET_SCHEDULER_TaskCallback trigger, + void *trigger_cls, + const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, + uint64_t code, + const void *data, + size_t data_length) +{ + struct ANASTASIS_AUTHORIZATION_State *as; + + as = GNUNET_new (struct ANASTASIS_AUTHORIZATION_State); + as->cls = cls; + as->truth_uuid = *truth_uuid; + as->code = code; + as->filename = GNUNET_strndup (data, + data_length); + return as; +} + + +/** + * Begin issuing authentication challenge to user based on @a data. + * I.e. start to send SMS or e-mail or launch video identification. + * + * @param as authorization state + * @param connection HTTP client request (for queuing response, such as redirection to video portal) + * @return state of the request + */ +static enum ANASTASIS_AUTHORIZATION_Result +file_process (struct ANASTASIS_AUTHORIZATION_State *as, + struct MHD_Connection *connection) +{ + const char *mime; + const char *lang; + + mime = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT); + if (NULL == mime) + mime = "text/plain"; + lang = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT_LANGUAGE); + if (NULL == lang) + lang = "en"; + { + FILE *f = fopen (as->filename, "w"); + + if (NULL == f) + { + struct MHD_Response *resp; + MHD_RESULT mres; + + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "open", + as->filename); + resp = TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + "open"); + mres = MHD_queue_response (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + resp); + MHD_destroy_response (resp); + if (MHD_YES != mres) + return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_RES_FAILED; + } + + /* print challenge code to file */ + if (0 >= fprintf (f, + "%lu", + as->code)) + { + struct MHD_Response *resp; + MHD_RESULT mres; + + GNUNET_break (0 == fclose (f)); + resp = TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + "write"); + mres = MHD_queue_response (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + resp); + MHD_destroy_response (resp); + if (MHD_YES != mres) + return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_RES_FAILED; + } + GNUNET_break (0 == fclose (f)); + } + + /* Build HTTP response */ + { + struct MHD_Response *resp; + + if (TALER_MHD_xmime_matches (mime, + "application/json")) + { + json_t *body; + + body = json_pack ("{s:s}", + "filename", + as->filename); + GNUNET_break (NULL != body); + resp = TALER_MHD_make_json (body); + } + else + { + size_t response_size; + char *response; + + response_size = GNUNET_asprintf (&response, + _ ("Challenge written to file")); + resp = MHD_create_response_from_buffer (response_size, + response, + MHD_RESPMEM_MUST_COPY); + GNUNET_free (response); + TALER_MHD_add_global_headers (resp); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/plain")); + } + + { + MHD_RESULT mres; + + mres = MHD_queue_response (connection, + MHD_HTTP_FORBIDDEN, + resp); + MHD_destroy_response (resp); + if (MHD_YES != mres) + return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_RES_SUCCESS; + } + } +} + + +/** + * Free internal state associated with @a as. + * + * @param as state to clean up + */ +static void +file_cleanup (struct ANASTASIS_AUTHORIZATION_State *as) +{ + GNUNET_free (as->filename); + GNUNET_free (as); +} + + +/** + * Initialize File based authorization plugin + * + * @param cls a configuration instance + * @return NULL on error, otherwise a `struct ANASTASIS_AuthorizationPlugin` + */ +void * +libanastasis_plugin_authorization_file_init (void *cls) +{ + struct ANASTASIS_AuthorizationPlugin *plugin; + + plugin = GNUNET_new (struct ANASTASIS_AuthorizationPlugin); + plugin->code_validity_period = GNUNET_TIME_UNIT_MINUTES; + plugin->code_rotation_period = GNUNET_TIME_UNIT_MINUTES; + plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_MINUTES; + plugin->validate = &file_validate; + plugin->start = &file_start; + plugin->process = &file_process; + plugin->cleanup = &file_cleanup; + return plugin; +} + + +/** + * Unload authorization plugin + * + * @param cls a `struct ANASTASIS_AuthorizationPlugin` + * @return NULL (always) + */ +void * +libanastasis_plugin_authorization_file_done (void *cls) +{ + struct ANASTASIS_AuthorizationPlugin *plugin = cls; + + GNUNET_free (plugin); + return NULL; +} |