challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

commit 514c686914b896df996537f24b865d005a8f7b39
parent 8af7933c17dba30eb0a73166b24d7a77f6a8b8d4
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 20 Apr 2023 23:59:29 +0200

clean up high-level challenger dispatcher

Diffstat:
Msrc/challenger/Makefile.am | 1+
Msrc/challenger/challenger-httpd.c | 171+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/challenger/challenger-httpd.h | 111++++++++++++++++++++++++++++++++++++-------------------------------------------
Msrc/challenger/challenger-httpd_config.c | 24++++++------------------
Msrc/challenger/challenger-httpd_config.h | 8++------
Asrc/challenger/challenger-httpd_login.c | 36++++++++++++++++++++++++++++++++++++
Asrc/challenger/challenger-httpd_login.h | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/challenger/challenger-httpd_mhd.c | 56+++++++++++++-------------------------------------------
Msrc/challenger/challenger-httpd_mhd.h | 39++++++++++++++-------------------------
9 files changed, 257 insertions(+), 230 deletions(-)

diff --git a/src/challenger/Makefile.am b/src/challenger/Makefile.am @@ -27,6 +27,7 @@ challenger_admin_LDADD = \ challenger_httpd_SOURCES = \ challenger-httpd.c challenger-httpd.h \ challenger-httpd_config.c challenger-httpd_config.h \ + challenger-httpd_login.c challenger-httpd_login.h \ challenger-httpd_mhd.c challenger-httpd_mhd.h challenger_httpd_LDADD = \ $(top_builddir)/src/util/libchallengerutil.la \ diff --git a/src/challenger/challenger-httpd.c b/src/challenger/challenger-httpd.c @@ -24,6 +24,7 @@ #include <gnunet/gnunet_curl_lib.h> #include "challenger_util.h" #include "challenger-httpd.h" +#include "challenger-httpd_login.h" #include "challenger-httpd_mhd.h" #include "challenger_database_lib.h" #include "challenger-httpd_config.h" @@ -121,102 +122,116 @@ url_handler (void *cls, { static struct CH_RequestHandler handlers[] = { /* Landing page, tell humans to go away. */ - { "/", MHD_HTTP_METHOD_GET, "text/plain", - "Hello, I'm challenger. This HTTP server is not for humans.\n", 0, - &CH_MHD_handler_static_response, MHD_HTTP_OK }, - { "/agpl", MHD_HTTP_METHOD_GET, "text/plain", - NULL, 0, - &CH_handler_config, MHD_HTTP_FOUND }, - { "/config", MHD_HTTP_METHOD_GET, "text/json", - NULL, 0, - &CH_handler_config, MHD_HTTP_OK }, - {NULL, NULL, NULL, NULL, 0, 0 } - }; - static struct CH_RequestHandler h404 = { - "", NULL, "text/html", - "<html><title>404: not found</title></html>", 0, - &CH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND + { + .url = "/", + .method = MHD_HTTP_METHOD_GET, + .handler = &CH_MHD_handler_root + }, + { + .url = "/agpl", + .method = MHD_HTTP_METHOD_GET, + .handler = &CH_handler_config + }, + { + .url = "/config", + .method = MHD_HTTP_METHOD_GET, + .handler = &CH_handler_config + }, + { + .url = "/login", + .method = MHD_HTTP_METHOD_GET, + .handler = &CH_handler_login + }, + { + NULL, NULL, NULL + } }; - - struct TM_HandlerContext *hc; - struct GNUNET_AsyncScopeId aid; - const char *correlation_id = NULL; + struct CH_HandlerContext *hc; (void) cls; (void) version; hc = *con_cls; if (NULL == hc) { - GNUNET_async_scope_fresh (&aid); + const char *correlation_id; + bool found = false; + + hc = GNUNET_new (struct CH_HandlerContext); + hc->connection = connection; + GNUNET_async_scope_fresh (&hc->async_scope_id); + GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id); /* We only read the correlation ID on the first callback for every client */ correlation_id = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Challenger-Correlation-Id"); - if ((NULL != correlation_id) && - (GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id))) + if ( (NULL != correlation_id) && + (GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id)) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "illegal incoming correlation ID\n"); + "Illegal incoming correlation ID\n"); correlation_id = NULL; } - } - else - { - aid = hc->async_scope_id; - } - GNUNET_SCHEDULER_begin_async_scope (&aid); - - if (NULL != correlation_id) - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling request for (%s) URL '%s', correlation_id=%s\n", - method, - url, - correlation_id); - else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Handling request (%s) for URL '%s'\n", - method, - url); - - for (unsigned int i = 0; NULL != handlers[i].url; i++) - { - struct CH_RequestHandler *rh = &handlers[i]; - - if (0 == strcmp (url, - rh->url)) + if (NULL != correlation_id) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling request for (%s) URL '%s', correlation_id=%s\n", + method, + url, + correlation_id); + else + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling request (%s) for URL '%s'\n", + method, + url); + + for (unsigned int i = 0; NULL != handlers[i].url; i++) { - if (0 == strcasecmp (method, - MHD_HTTP_METHOD_OPTIONS)) - { - return TALER_MHD_reply_cors_preflight (connection); - } - if ( (NULL == rh->method) || - (0 == strcasecmp (method, - rh->method)) ) + struct CH_RequestHandler *rh = &handlers[i]; + + if (0 == strcmp (url, + rh->url)) { - MHD_RESULT ret; - - ret = rh->handler (rh, - connection, - con_cls, - upload_data, - upload_data_size); - hc = *con_cls; - if (NULL != hc) + found = true; + if (0 == strcasecmp (method, + MHD_HTTP_METHOD_OPTIONS)) + { + return TALER_MHD_reply_cors_preflight (connection); + } + if ( (NULL == rh->method) || + (0 == strcasecmp (method, + rh->method)) ) { - /* Store the async context ID, so we can restore it if - * we get another callback for this request. */ - hc->async_scope_id = aid; + hc->rh = rh; + break; } - return ret; } } + if (NULL == hc->rh) + { + GNUNET_break_op (0); + if (found) + { + /* TOOD: return which methods are allowed ... */ + return TALER_MHD_reply_static (hc->connection, + MHD_HTTP_METHOD_NOT_ALLOWED, + "text/plain", + NULL, + 0); + } + return TALER_MHD_reply_static (hc->connection, + MHD_HTTP_NOT_FOUND, + "text/plain", + NULL, + 0); + } + } + else + { + GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id); } - return CH_MHD_handler_static_response (&h404, - connection, - con_cls, - upload_data, - upload_data_size); + GNUNET_assert (NULL != hc->rh); + return hc->rh->handler (hc, + upload_data, + upload_data_size); } @@ -278,16 +293,18 @@ handle_mhd_completion_callback (void *cls, void **con_cls, enum MHD_RequestTerminationCode toe) { - struct TM_HandlerContext *hc = *con_cls; + struct CH_HandlerContext *hc = *con_cls; (void) cls; - (void) connection; if (NULL == hc) return; + GNUNET_assert (hc->connection == connection); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finished handling request with status %d\n", (int) toe); - hc->cc (hc); + if (NULL != hc->cc) + hc->cc (hc->ctx); + GNUNET_free (hc); *con_cls = NULL; } diff --git a/src/challenger/challenger-httpd.h b/src/challenger/challenger-httpd.h @@ -27,99 +27,88 @@ #include "challenger_database_lib.h" #include <gnunet/gnunet_mhd_compat.h> + /** * @brief Struct describing an URL and the handler for it. */ -struct CH_RequestHandler -{ +struct CH_RequestHandler; - /** - * URL the handler is for. - */ - const char *url; +/** + * Signature of a function used to clean up the context + * of this handler. + * + * @param cls closure to clean up. + */ +typedef void +(*CH_ContextCleanup)(void *cls); - /** - * Method the handler is for, NULL for "all". - */ - const char *method; + +/** + * Each MHD response handler that sets the "connection_cls" to a + * non-NULL value must use a struct that has this struct as its first + * member. This struct contains a single callback, which will be + * invoked to clean up the memory when the connection is completed. + */ +struct CH_HandlerContext +{ /** - * Mime type to use in reply (hint, can be NULL). + * Function to execute the handler-specific cleanup of the + * (typically larger) context. */ - const char *mime_type; + CH_ContextCleanup cc; /** - * Raw data for the @e handler + * Handler-specific context, will be passed to @e cc + * upon completion. */ - const void *data; + void *ctx; /** - * Number of bytes in @e data, 0 for 0-terminated. + * Connection being processed. */ - size_t data_size; + struct MHD_Connection *connection; /** - * Function to call to handle the request. - * - * @param rh this struct - * @param mime_type the @e mime_type for the reply (hint, can be NULL) - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code + * Request handler for this request. */ - MHD_RESULT (*handler)(struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); + const struct CH_RequestHandler *rh; /** - * Default response code. + * Asynchronous request context id. */ - unsigned int response_code; + struct GNUNET_AsyncScopeId async_scope_id; }; /** - * Each MHD response handler that sets the "connection_cls" to a - * non-NULL value must use a struct that has this struct as its first - * member. This struct contains a single callback, which will be - * invoked to clean up the memory when the contection is completed. - */ -struct TM_HandlerContext; - -/** - * Signature of a function used to clean up the context - * we keep in the "connection_cls" of MHD when handling - * a request. - * - * @param hc header of the context to clean up. - */ -typedef void -(*TM_ContextCleanup)(struct TM_HandlerContext *hc); - - -/** - * Each MHD response handler that sets the "connection_cls" to a - * non-NULL value must use a struct that has this struct as its first - * member. This struct contains a single callback, which will be - * invoked to clean up the memory when the connection is completed. + * @brief Struct describing an URL and the handler for it. */ -struct TM_HandlerContext +struct CH_RequestHandler { /** - * Function to execute the handler-specific cleanup of the - * (typically larger) context. + * URL the handler is for. */ - TM_ContextCleanup cc; + const char *url; /** - * Asynchronous request context id. + * Method the handler is for, NULL for "all". */ - struct GNUNET_AsyncScopeId async_scope_id; + const char *method; + + /** + * Function to call to handle the request. + * + * @param hc handler context + * @param upload_data upload data + * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @return MHD result code + */ + MHD_RESULT (*handler)(struct CH_HandlerContext *hc, + const char *upload_data, + size_t *upload_data_size); + }; diff --git a/src/challenger/challenger-httpd_config.c b/src/challenger/challenger-httpd_config.c @@ -1,6 +1,6 @@ /* This file is part of Challenger - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2023 Taler Systems SA Challenger 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 @@ -27,30 +27,18 @@ * Protocol version history: * * 0: original design - * 1: adds ?fresh=y to POST backup operation to force fresh contract - * to be created */ -/** - * Manages a /config call. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @param mi merchant backend instance, never NULL - * @return MHD result code - */ + MHD_RESULT -CH_handler_config (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, +CH_handler_config (struct CH_HandlerContext *hc, const char *upload_data, size_t *upload_data_size) { + (void) upload_data; + (void) upload_data_size; return TALER_MHD_REPLY_JSON_PACK ( - connection, + hc->connection, MHD_HTTP_OK, GNUNET_JSON_pack_string ("name", "challenger"), diff --git a/src/challenger/challenger-httpd_config.h b/src/challenger/challenger-httpd_config.h @@ -26,17 +26,13 @@ /** * Manages a /config call. * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) + * @param[in,out] hc context of the connection * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code */ MHD_RESULT -CH_handler_config (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, +CH_handler_config (struct CH_HandlerContext *hc, const char *upload_data, size_t *upload_data_size); diff --git a/src/challenger/challenger-httpd_login.c b/src/challenger/challenger-httpd_login.c @@ -0,0 +1,36 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger 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, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file challenger-httpd_login.c + * @brief functions to handle incoming requests for logins + * @author Christian Grothoff + */ +#include "platform.h" +#include "challenger-httpd.h" +#include <gnunet/gnunet_util_lib.h> +#include "challenger-httpd_login.h" + + +MHD_RESULT +CH_handler_login (struct CH_HandlerContext *hc, + const char *upload_data, + size_t *upload_data_size) +{ + return TALER_MHD_reply_with_error (hc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + NULL); +} diff --git a/src/challenger/challenger-httpd_login.h b/src/challenger/challenger-httpd_login.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2023 Taler Systems SA + + TALER 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, or (at your option) any later version. + + TALER 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 + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file challenger-httpd_policy.h + * @brief functions to handle incoming requests on /login + * @author Christian Grothoff + */ +#ifndef CHALLENGER_HTTPD_LOGIN_H +#define CHALLENGER_HTTPD_LOGIN_H + +#include <microhttpd.h> + + +/** + * Handle request on @a connection for /login. + * + * @param hc context of the connection + * @param upload_data upload data, if any + * @param[in,out] upload_data_size remaining data in @a upload_data, to be updated + * @return MHD result code + */ +MHD_RESULT +CH_handler_login (struct CH_HandlerContext *hc, + const char *upload_data, + size_t *upload_data_size); + + +#endif diff --git a/src/challenger/challenger-httpd_mhd.c b/src/challenger/challenger-httpd_mhd.c @@ -16,8 +16,6 @@ /** * @file challenger-httpd_mhd.c * @brief helpers for MHD interaction - * @author Florian Dold - * @author Benedikt Mueller * @author Christian Grothoff */ #include "platform.h" @@ -25,60 +23,32 @@ #include "challenger-httpd_mhd.h" -/** - * Function to call to handle the request by sending - * back static data from the @a rh. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ MHD_RESULT -CH_MHD_handler_static_response (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) +CH_MHD_handler_root (struct CH_HandlerContext *hc, + const char *upload_data, + size_t *upload_data_size) { - (void) connection_cls; + const char *msg = + "Hello, I'm challenger. This HTTP server is not for humans.\n"; + (void) upload_data; (void) upload_data_size; - if (0 == rh->data_size) - rh->data_size = strlen ((const char *) rh->data); - return TALER_MHD_reply_static (connection, - rh->response_code, - rh->mime_type, - (void *) rh->data, - rh->data_size); + return TALER_MHD_reply_static (hc->connection, + MHD_HTTP_OK, + "text/plain", + msg, + strlen (msg)); } -/** - * Function to call to handle the request by sending - * back a redirect to the AGPL source code. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ MHD_RESULT -CH_MHD_handler_agpl_redirect (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, +CH_MHD_handler_agpl_redirect (struct CH_HandlerContext *hc, const char *upload_data, size_t *upload_data_size) { - (void) rh; - (void) connection_cls; (void) upload_data; (void) upload_data_size; - return TALER_MHD_reply_agpl (connection, + return TALER_MHD_reply_agpl (hc->connection, "https://git.taler.net/challenger.git"); } diff --git a/src/challenger/challenger-httpd_mhd.h b/src/challenger/challenger-httpd_mhd.h @@ -1,17 +1,17 @@ /* - This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. and INRIA + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA - TALER is free software; you can redistribute it and/or modify it under the + Challenger 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, or (at your option) any later version. - TALER is distributed in the hope that it will be useful, but WITHOUT ANY + Challenger 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 - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** @@ -21,49 +21,38 @@ * @author Benedikt Mueller * @author Christian Grothoff */ -#ifndef challenger_HTTPD_MHD_H -#define challenger_HTTPD_MHD_H +#ifndef CHALLENGER_HTTPD_MHD_H +#define CHALLENGER_HTTPD_MHD_H #include <gnunet/gnunet_util_lib.h> #include <microhttpd.h> #include "challenger-httpd.h" /** - * Function to call to handle the request by sending - * back static data from the @a rh. + * Function to call to for "/" requests. * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data + * @param[in,out] hc handler context * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @param mi merchant backend instance, NULL is allowed in this case! * @return MHD result code */ MHD_RESULT -CH_MHD_handler_static_response (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); +CH_MHD_handler_root (struct CH_HandlerContext *hc, + const char *upload_data, + size_t *upload_data_size); /** * Function to call to handle the request by sending * back a redirect to the AGPL source code. * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) + * @param hc handler context * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @param mi merchant backend instance, never NULL * @return MHD result code */ MHD_RESULT -CH_MHD_handler_agpl_redirect (struct CH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, +CH_MHD_handler_agpl_redirect (struct CH_HandlerContext *hc, const char *upload_data, size_t *upload_data_size);