commit 514c54aed35ae3e4b046abc3e059f46e67083e5f
parent cc8ff79d4dd67c09849efcbcc0f9c29a7c61f1eb
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 8 May 2023 17:03:22 +0200
rename /auth to /token
Diffstat:
14 files changed, 608 insertions(+), 608 deletions(-)
diff --git a/src/challenger/Makefile.am b/src/challenger/Makefile.am
@@ -37,7 +37,6 @@ challenger_admin_LDADD = \
challenger_httpd_SOURCES = \
challenger-httpd.c challenger-httpd.h \
- challenger-httpd_auth.c challenger-httpd_auth.h \
challenger-httpd_challenge.c challenger-httpd_challenge.h \
challenger-httpd_common.c challenger-httpd_common.h \
challenger-httpd_config.c challenger-httpd_config.h \
@@ -45,7 +44,8 @@ challenger_httpd_SOURCES = \
challenger-httpd_login.c challenger-httpd_login.h \
challenger-httpd_mhd.c challenger-httpd_mhd.h \
challenger-httpd_setup.c challenger-httpd_setup.h \
- challenger-httpd_solve.c challenger-httpd_solve.h
+ challenger-httpd_solve.c challenger-httpd_solve.h \
+ challenger-httpd_token.c challenger-httpd_token.h
challenger_httpd_LDADD = \
$(top_builddir)/src/util/libchallengerutil.la \
$(top_builddir)/src/challengerdb/libchallengerdb.la \
diff --git a/src/challenger/challenger-httpd.c b/src/challenger/challenger-httpd.c
@@ -24,13 +24,13 @@
#include <gnunet/gnunet_curl_lib.h>
#include "challenger_util.h"
#include "challenger-httpd.h"
-#include "challenger-httpd_auth.h"
#include "challenger-httpd_challenge.h"
#include "challenger-httpd_info.h"
#include "challenger-httpd_setup.h"
#include "challenger-httpd_login.h"
#include "challenger-httpd_mhd.h"
#include "challenger-httpd_solve.h"
+#include "challenger-httpd_token.h"
#include "challenger_database_lib.h"
#include "challenger-httpd_config.h"
#include <taler/taler_templating_lib.h>
@@ -197,9 +197,9 @@ url_handler (void *cls,
.handler = &CH_handler_solve
},
{
- .url = "/auth",
+ .url = "/token",
.method = MHD_HTTP_METHOD_POST,
- .handler = &CH_handler_auth
+ .handler = &CH_handler_token
},
{
.url = "/info",
diff --git a/src/challenger/challenger-httpd_auth.c b/src/challenger/challenger-httpd_auth.c
@@ -1,442 +0,0 @@
-/*
- 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_auth.c
- * @brief functions to handle incoming /auth requests
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "challenger-httpd.h"
-#include <gnunet/gnunet_util_lib.h>
-#include "challenger-httpd_auth.h"
-#include "challenger-httpd_common.h"
-#include <taler/taler_json_lib.h>
-#include <taler/taler_merchant_service.h>
-#include <taler/taler_signatures.h>
-
-
-/**
- * Context for a /auth operation.
- */
-struct AuthContext
-{
-
- /**
- * Nonce of the validation process the request is about.
- */
- struct CHALLENGER_ValidationNonceP nonce;
-
- /**
- * Handle for processing uploaded data.
- */
- struct MHD_PostProcessor *pp;
-
- /**
- * Uploaded 'client_id' field from POST data.
- */
- char *client_id;
-
- /**
- * Uploaded 'client_id' field from POST data.
- */
- char *redirect_uri;
-
- /**
- * Uploaded 'client_secret' field from POST data.
- */
- char *client_secret;
-
- /**
- * Uploaded 'code' field from POST data.
- */
- char *code;
-
- /**
- * Uploaded 'grant_type' field from POST data.
- */
- char *grant_type;
-};
-
-
-/**
- * Function called to clean up a backup context.
- *
- * @param cls a `struct AuthContext`
- */
-static void
-cleanup_ctx (void *cls)
-{
- struct AuthContext *bc = cls;
-
- if (NULL != bc->pp)
- {
- GNUNET_break_op (MHD_YES ==
- MHD_destroy_post_processor (bc->pp));
- }
- GNUNET_free (bc->client_id);
- GNUNET_free (bc->redirect_uri);
- GNUNET_free (bc->client_secret);
- GNUNET_free (bc->code);
- GNUNET_free (bc->grant_type);
- GNUNET_free (bc);
-}
-
-
-/**
- * Iterator over key-value pairs where the value may be made available
- * in increments and/or may not be zero-terminated. Used for
- * processing POST data.
- *
- * @param cls a `struct AuthContext *`
- * @param kind type of the value, always #MHD_POSTDATA_KIND when called from MHD
- * @param key 0-terminated key for the value
- * @param filename name of the uploaded file, NULL if not known
- * @param content_type mime-type of the data, NULL if not known
- * @param transfer_encoding encoding of the data, NULL if not known
- * @param data pointer to @a size bytes of data at the
- * specified offset
- * @param off offset of data in the overall value
- * @param size number of bytes in @a data available
- * @return #MHD_YES to continue iterating,
- * #MHD_NO to abort the iteration
- */
-static enum MHD_Result
-post_iter (void *cls,
- enum MHD_ValueKind kind,
- const char *key,
- const char *filename,
- const char *content_type,
- const char *transfer_encoding,
- const char *data,
- uint64_t off,
- size_t size)
-{
- struct AuthContext *bc = cls;
- struct Map
- {
- const char *name;
- char **ptr;
- } map[] = {
- {
- .name = "client_id",
- .ptr = &bc->client_id
- },
- {
- .name = "redirect_uri",
- .ptr = &bc->redirect_uri
- },
- {
- .name = "client_secret",
- .ptr = &bc->client_secret
- },
- {
- .name = "code",
- .ptr = &bc->code
- },
- {
- .name = "grant_type",
- .ptr = &bc->grant_type
- },
- {
- .name = NULL,
- .ptr = NULL
- },
- };
- char **ptr = NULL;
- size_t slen;
-
- (void) kind;
- (void) filename;
- (void) content_type;
- (void) transfer_encoding;
- (void) off;
- for (unsigned int i = 0; NULL != map[i].name; i++)
- if (0 == strcmp (key,
- map[i].name))
- ptr = map[i].ptr;
- if (NULL == ptr)
- return MHD_YES; /* ignore */
- if (NULL == *ptr)
- slen = 0;
- else
- slen = strlen (*ptr);
- if (NULL == *ptr)
- *ptr = GNUNET_malloc (size + 1);
- else
- *ptr = GNUNET_realloc (*ptr,
- slen + size + 1);
- memcpy (&(*ptr)[slen],
- data,
- size);
- return MHD_YES;
-}
-
-
-MHD_RESULT
-CH_handler_auth (struct CH_HandlerContext *hc,
- const char *upload_data,
- size_t *upload_data_size)
-{
- struct AuthContext *bc = hc->ctx;
-
- if (NULL == bc)
- {
- /* first call, setup internals */
- bc = GNUNET_new (struct AuthContext);
- hc->cc = &cleanup_ctx;
- hc->ctx = bc;
- bc->pp = MHD_create_post_processor (hc->connection,
- 2 * 1024,
- &post_iter,
- bc);
- TALER_MHD_check_content_length (hc->connection,
- 2 * 1024);
- return MHD_YES;
- }
- /* handle upload */
- if (0 != *upload_data_size)
- {
- enum MHD_Result res;
-
- res = MHD_post_process (bc->pp,
- upload_data,
- *upload_data_size);
- *upload_data_size = 0;
- if (MHD_YES == res)
- return MHD_YES;
- return MHD_NO;
- }
- if ( (NULL == bc->grant_type) ||
- (0 != strcmp (bc->grant_type,
- "authorization_code")) )
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "authorization_code");
- }
-
- if (NULL == bc->code)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MISSING,
- "code");
- }
- if (NULL == bc->client_secret)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MISSING,
- "client_secret");
- }
- if (NULL == bc->client_id)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MISSING,
- "client_id");
- }
- if (NULL == bc->redirect_uri)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MISSING,
- "redirect_uri");
- }
-
- /* Check this client is authorized to access the service */
- {
- enum GNUNET_DB_QueryStatus qs;
- char *client_url = NULL;
- unsigned long long client_id;
- char dummy;
-
- if (1 != sscanf (bc->client_id,
- "%llu%c",
- &client_id,
- &dummy))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "client_id");
- }
-
- qs = CH_db->client_check (CH_db->cls,
- client_id,
- bc->client_secret,
- 0, /* do not increment */
- &client_url);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "client_check");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- if ( (NULL != client_url) &&
- (0 != strcmp (client_url,
- bc->redirect_uri)) )
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI,
- NULL);
- }
- GNUNET_free (client_url);
- }
-
- if (GNUNET_OK !=
- CH_code_to_nonce (bc->code,
- &bc->nonce))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE,
- NULL);
- }
-
- /* Check code is valid */
- {
- char *client_secret;
- char *address;
- char *client_scope;
- char *client_state;
- char *client_redirect_url;
- enum GNUNET_DB_QueryStatus qs;
- char *code;
-
- qs = CH_db->validation_get (CH_db->cls,
- &bc->nonce,
- &client_secret,
- &address,
- &client_scope,
- &client_state,
- &client_redirect_url);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "validation_get");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
- "validation_get");
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- code = CH_compute_code (&bc->nonce,
- client_secret,
- client_scope,
- address,
- client_redirect_url);
- GNUNET_free (address);
- GNUNET_free (client_scope);
- GNUNET_free (client_secret);
- GNUNET_free (client_redirect_url);
- GNUNET_free (client_state);
- if (0 != strcmp (code,
- bc->code))
- {
- GNUNET_break_op (0);
- GNUNET_free (code);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE,
- "code");
- }
- GNUNET_free (code);
- }
-
- {
- struct CHALLENGER_AccessTokenP grant;
- enum GNUNET_DB_QueryStatus qs;
- /* FIXME: do not hard-code 1h? */
- struct GNUNET_TIME_Relative grant_expiration
- = GNUNET_TIME_UNIT_HOURS;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &grant,
- sizeof (grant));
- qs = CH_db->auth_add_grant (CH_db->cls,
- &bc->nonce,
- &grant,
- grant_expiration,
- CH_validation_expiration);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "auth_add_grant");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (hc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GRANT_UNKNOWN,
- "auth_add_grant");
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
-
-
- return TALER_MHD_REPLY_JSON_PACK (
- hc->connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_data_auto ("access_token",
- &grant),
- GNUNET_JSON_pack_string ("token_type",
- "Bearer"),
- GNUNET_JSON_pack_uint64 ("expires_in",
- grant_expiration.rel_value_us
- / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
- }
-}
diff --git a/src/challenger/challenger-httpd_auth.h b/src/challenger/challenger-httpd_auth.h
@@ -1,41 +0,0 @@
-/*
- 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_auth.h
- * @brief functions to handle incoming requests on /auth
- * @author Christian Grothoff
- */
-#ifndef AUTHR_HTTPD_AUTH_H
-#define AUTHR_HTTPD_AUTH_H
-
-#include <microhttpd.h>
-
-
-/**
- * Handle a client POSTing a /auth request
- *
- * @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_auth (struct CH_HandlerContext *hc,
- const char *upload_data,
- size_t *upload_data_size);
-
-
-#endif
diff --git a/src/challenger/challenger-httpd_token.c b/src/challenger/challenger-httpd_token.c
@@ -0,0 +1,442 @@
+/*
+ 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_token.c
+ * @brief functions to handle incoming /token requests
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "challenger-httpd.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "challenger-httpd_token.h"
+#include "challenger-httpd_common.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_merchant_service.h>
+#include <taler/taler_signatures.h>
+
+
+/**
+ * Context for a /token operation.
+ */
+struct TokenContext
+{
+
+ /**
+ * Nonce of the validation process the request is about.
+ */
+ struct CHALLENGER_ValidationNonceP nonce;
+
+ /**
+ * Handle for processing uploaded data.
+ */
+ struct MHD_PostProcessor *pp;
+
+ /**
+ * Uploaded 'client_id' field from POST data.
+ */
+ char *client_id;
+
+ /**
+ * Uploaded 'client_id' field from POST data.
+ */
+ char *redirect_uri;
+
+ /**
+ * Uploaded 'client_secret' field from POST data.
+ */
+ char *client_secret;
+
+ /**
+ * Uploaded 'code' field from POST data.
+ */
+ char *code;
+
+ /**
+ * Uploaded 'grant_type' field from POST data.
+ */
+ char *grant_type;
+};
+
+
+/**
+ * Function called to clean up a backup context.
+ *
+ * @param cls a `struct TokenContext`
+ */
+static void
+cleanup_ctx (void *cls)
+{
+ struct TokenContext *bc = cls;
+
+ if (NULL != bc->pp)
+ {
+ GNUNET_break_op (MHD_YES ==
+ MHD_destroy_post_processor (bc->pp));
+ }
+ GNUNET_free (bc->client_id);
+ GNUNET_free (bc->redirect_uri);
+ GNUNET_free (bc->client_secret);
+ GNUNET_free (bc->code);
+ GNUNET_free (bc->grant_type);
+ GNUNET_free (bc);
+}
+
+
+/**
+ * Iterator over key-value pairs where the value may be made available
+ * in increments and/or may not be zero-terminated. Used for
+ * processing POST data.
+ *
+ * @param cls a `struct TokenContext *`
+ * @param kind type of the value, always #MHD_POSTDATA_KIND when called from MHD
+ * @param key 0-terminated key for the value
+ * @param filename name of the uploaded file, NULL if not known
+ * @param content_type mime-type of the data, NULL if not known
+ * @param transfer_encoding encoding of the data, NULL if not known
+ * @param data pointer to @a size bytes of data at the
+ * specified offset
+ * @param off offset of data in the overall value
+ * @param size number of bytes in @a data available
+ * @return #MHD_YES to continue iterating,
+ * #MHD_NO to abort the iteration
+ */
+static enum MHD_Result
+post_iter (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data,
+ uint64_t off,
+ size_t size)
+{
+ struct TokenContext *bc = cls;
+ struct Map
+ {
+ const char *name;
+ char **ptr;
+ } map[] = {
+ {
+ .name = "client_id",
+ .ptr = &bc->client_id
+ },
+ {
+ .name = "redirect_uri",
+ .ptr = &bc->redirect_uri
+ },
+ {
+ .name = "client_secret",
+ .ptr = &bc->client_secret
+ },
+ {
+ .name = "code",
+ .ptr = &bc->code
+ },
+ {
+ .name = "grant_type",
+ .ptr = &bc->grant_type
+ },
+ {
+ .name = NULL,
+ .ptr = NULL
+ },
+ };
+ char **ptr = NULL;
+ size_t slen;
+
+ (void) kind;
+ (void) filename;
+ (void) content_type;
+ (void) transfer_encoding;
+ (void) off;
+ for (unsigned int i = 0; NULL != map[i].name; i++)
+ if (0 == strcmp (key,
+ map[i].name))
+ ptr = map[i].ptr;
+ if (NULL == ptr)
+ return MHD_YES; /* ignore */
+ if (NULL == *ptr)
+ slen = 0;
+ else
+ slen = strlen (*ptr);
+ if (NULL == *ptr)
+ *ptr = GNUNET_malloc (size + 1);
+ else
+ *ptr = GNUNET_realloc (*ptr,
+ slen + size + 1);
+ memcpy (&(*ptr)[slen],
+ data,
+ size);
+ return MHD_YES;
+}
+
+
+MHD_RESULT
+CH_handler_token (struct CH_HandlerContext *hc,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ struct TokenContext *bc = hc->ctx;
+
+ if (NULL == bc)
+ {
+ /* first call, setup internals */
+ bc = GNUNET_new (struct TokenContext);
+ hc->cc = &cleanup_ctx;
+ hc->ctx = bc;
+ bc->pp = MHD_create_post_processor (hc->connection,
+ 2 * 1024,
+ &post_iter,
+ bc);
+ TALER_MHD_check_content_length (hc->connection,
+ 2 * 1024);
+ return MHD_YES;
+ }
+ /* handle upload */
+ if (0 != *upload_data_size)
+ {
+ enum MHD_Result res;
+
+ res = MHD_post_process (bc->pp,
+ upload_data,
+ *upload_data_size);
+ *upload_data_size = 0;
+ if (MHD_YES == res)
+ return MHD_YES;
+ return MHD_NO;
+ }
+ if ( (NULL == bc->grant_type) ||
+ (0 != strcmp (bc->grant_type,
+ "authorization_code")) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "authorization_code");
+ }
+
+ if (NULL == bc->code)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "code");
+ }
+ if (NULL == bc->client_secret)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "client_secret");
+ }
+ if (NULL == bc->client_id)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "client_id");
+ }
+ if (NULL == bc->redirect_uri)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "redirect_uri");
+ }
+
+ /* Check this client is authorized to access the service */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ char *client_url = NULL;
+ unsigned long long client_id;
+ char dummy;
+
+ if (1 != sscanf (bc->client_id,
+ "%llu%c",
+ &client_id,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "client_id");
+ }
+
+ qs = CH_db->client_check (CH_db->cls,
+ client_id,
+ bc->client_secret,
+ 0, /* do not increment */
+ &client_url);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "client_check");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return MHD_NO;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ if ( (NULL != client_url) &&
+ (0 != strcmp (client_url,
+ bc->redirect_uri)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI,
+ NULL);
+ }
+ GNUNET_free (client_url);
+ }
+
+ if (GNUNET_OK !=
+ CH_code_to_nonce (bc->code,
+ &bc->nonce))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE,
+ NULL);
+ }
+
+ /* Check code is valid */
+ {
+ char *client_secret;
+ char *address;
+ char *client_scope;
+ char *client_state;
+ char *client_redirect_url;
+ enum GNUNET_DB_QueryStatus qs;
+ char *code;
+
+ qs = CH_db->validation_get (CH_db->cls,
+ &bc->nonce,
+ &client_secret,
+ &address,
+ &client_scope,
+ &client_state,
+ &client_redirect_url);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "validation_get");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return MHD_NO;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
+ "validation_get");
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ code = CH_compute_code (&bc->nonce,
+ client_secret,
+ client_scope,
+ address,
+ client_redirect_url);
+ GNUNET_free (address);
+ GNUNET_free (client_scope);
+ GNUNET_free (client_secret);
+ GNUNET_free (client_redirect_url);
+ GNUNET_free (client_state);
+ if (0 != strcmp (code,
+ bc->code))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (code);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE,
+ "code");
+ }
+ GNUNET_free (code);
+ }
+
+ {
+ struct CHALLENGER_AccessTokenP grant;
+ enum GNUNET_DB_QueryStatus qs;
+ /* FIXME: do not hard-code 1h? */
+ struct GNUNET_TIME_Relative grant_expiration
+ = GNUNET_TIME_UNIT_HOURS;
+
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ &grant,
+ sizeof (grant));
+ qs = CH_db->token_add_grant (CH_db->cls,
+ &bc->nonce,
+ &grant,
+ grant_expiration,
+ CH_validation_expiration);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "token_add_grant");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return MHD_NO;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GRANT_UNKNOWN,
+ "token_add_grant");
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+
+
+ return TALER_MHD_REPLY_JSON_PACK (
+ hc->connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_data_auto ("access_token",
+ &grant),
+ GNUNET_JSON_pack_string ("token_type",
+ "Bearer"),
+ GNUNET_JSON_pack_uint64 ("expires_in",
+ grant_expiration.rel_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
+ }
+}
diff --git a/src/challenger/challenger-httpd_token.h b/src/challenger/challenger-httpd_token.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_token.h
+ * @brief functions to handle incoming requests on /token
+ * @author Christian Grothoff
+ */
+#ifndef AUTHR_HTTPD_TOKEN_H
+#define AUTHR_HTTPD_TOKEN_H
+
+#include <microhttpd.h>
+
+
+/**
+ * Handle a client POSTing a /token request
+ *
+ * @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_token (struct CH_HandlerContext *hc,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+#endif
diff --git a/src/challenger/test-challenger.sh b/src/challenger/test-challenger.sh
@@ -156,7 +156,7 @@ fi
echo "OK"
echo -n "Requesting authorization for client ..."
-STATUS=$(curl "${BURL}/auth" \
+STATUS=$(curl "${BURL}/token" \
-X POST \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "redirect_uri=${REDIRECT_URI}" \
diff --git a/src/challengerdb/Makefile.am b/src/challengerdb/Makefile.am
@@ -61,7 +61,7 @@ libchallenger_plugin_db_postgres_la_SOURCES = \
pg_client_delete.h pg_client_delete.c \
pg_client_check.h pg_client_check.c \
pg_info_get_grant.h pg_info_get_grant.c \
- pg_auth_add_grant.h pg_auth_add_grant.c \
+ pg_token_add_grant.h pg_token_add_grant.c \
pg_setup_nonce.h pg_setup_nonce.c \
pg_login_start.h pg_login_start.c \
pg_challenge_set_address_and_pin.h pg_challenge_set_address_and_pin.c \
diff --git a/src/challengerdb/pg_auth_add_grant.c b/src/challengerdb/pg_auth_add_grant.c
@@ -1,62 +0,0 @@
-/*
- 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 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file challengerdb/pg_auth_add_grant.c
- * @brief Implementation of the auth_add_grant function for Postgres
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <taler/taler_error_codes.h>
-#include <taler/taler_dbevents.h>
-#include <taler/taler_pq_lib.h>
-#include "pg_auth_add_grant.h"
-#include "pg_helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-CH_PG_auth_add_grant (
- void *cls,
- const struct CHALLENGER_ValidationNonceP *nonce,
- const struct CHALLENGER_AccessTokenP *grant,
- struct GNUNET_TIME_Relative grant_expiration,
- struct GNUNET_TIME_Relative address_expiration)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_TIME_Absolute ge
- = GNUNET_TIME_relative_to_absolute (grant_expiration);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (nonce),
- GNUNET_PQ_query_param_auto_from_type (grant),
- GNUNET_PQ_query_param_absolute_time (&ge),
- GNUNET_PQ_query_param_relative_time (&address_expiration),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "auth_add_grant",
- "INSERT INTO grants"
- " (access_token"
- " ,address"
- " ,grant_expiration_time"
- " ,address_expiration_time"
- ") SELECT"
- " $2, address, $3, $4 + last_tx_time"
- " FROM validations"
- " WHERE nonce=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "auth_add_grant",
- params);
-}
diff --git a/src/challengerdb/pg_auth_add_grant.h b/src/challengerdb/pg_auth_add_grant.h
@@ -1,48 +0,0 @@
-/*
- 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 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file challengerdb/pg_auth_add_grant.h
- * @brief implementation of the auth_add_grant function for Postgres
- * @author Christian Grothoff
- */
-#ifndef PG_AUTH_ADD_GRANT_H
-#define PG_AUTH_ADD_GRANT_H
-
-#include <taler/taler_util.h>
-#include <taler/taler_json_lib.h>
-#include "challenger_database_plugin.h"
-
-
-/**
- * Add access @a grant to address under @a nonce.
- *
- * @param cls closure
- * @param nonce validation process to grant access to
- * @param grant grant token that grants access
- * @param grant_expiration for how long should the grant be valid
- * @param address_expiration for how long after validation do we consider addresses to be valid
- * @return transaction status
- */
-enum GNUNET_DB_QueryStatus
-CH_PG_auth_add_grant (
- void *cls,
- const struct CHALLENGER_ValidationNonceP *nonce,
- const struct CHALLENGER_AccessTokenP *grant,
- struct GNUNET_TIME_Relative grant_expiration,
- struct GNUNET_TIME_Relative address_expiration);
-
-
-#endif
diff --git a/src/challengerdb/pg_token_add_grant.c b/src/challengerdb/pg_token_add_grant.c
@@ -0,0 +1,62 @@
+/*
+ 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 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file challengerdb/pg_token_add_grant.c
+ * @brief Implementation of the token_add_grant function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_token_add_grant.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+CH_PG_token_add_grant (
+ void *cls,
+ const struct CHALLENGER_ValidationNonceP *nonce,
+ const struct CHALLENGER_AccessTokenP *grant,
+ struct GNUNET_TIME_Relative grant_expiration,
+ struct GNUNET_TIME_Relative address_expiration)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_TIME_Absolute ge
+ = GNUNET_TIME_relative_to_absolute (grant_expiration);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (nonce),
+ GNUNET_PQ_query_param_auto_from_type (grant),
+ GNUNET_PQ_query_param_absolute_time (&ge),
+ GNUNET_PQ_query_param_relative_time (&address_expiration),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "token_add_grant",
+ "INSERT INTO grants"
+ " (access_token"
+ " ,address"
+ " ,grant_expiration_time"
+ " ,address_expiration_time"
+ ") SELECT"
+ " $2, address, $3, $4 + last_tx_time"
+ " FROM validations"
+ " WHERE nonce=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "token_add_grant",
+ params);
+}
diff --git a/src/challengerdb/pg_token_add_grant.h b/src/challengerdb/pg_token_add_grant.h
@@ -0,0 +1,48 @@
+/*
+ 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 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file challengerdb/pg_token_add_grant.h
+ * @brief implementation of the token_add_grant function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_AUTH_ADD_GRANT_H
+#define PG_AUTH_ADD_GRANT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "challenger_database_plugin.h"
+
+
+/**
+ * Add access @a grant to address under @a nonce.
+ *
+ * @param cls closure
+ * @param nonce validation process to grant access to
+ * @param grant grant token that grants access
+ * @param grant_expiration for how long should the grant be valid
+ * @param address_expiration for how long after validation do we consider addresses to be valid
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+CH_PG_token_add_grant (
+ void *cls,
+ const struct CHALLENGER_ValidationNonceP *nonce,
+ const struct CHALLENGER_AccessTokenP *grant,
+ struct GNUNET_TIME_Relative grant_expiration,
+ struct GNUNET_TIME_Relative address_expiration);
+
+
+#endif
diff --git a/src/challengerdb/plugin_challengerdb_postgres.c b/src/challengerdb/plugin_challengerdb_postgres.c
@@ -29,7 +29,7 @@
#include "pg_client_add.h"
#include "pg_client_delete.h"
#include "pg_info_get_grant.h"
-#include "pg_auth_add_grant.h"
+#include "pg_token_add_grant.h"
#include "pg_client_check.h"
#include "pg_setup_nonce.h"
#include "pg_login_start.h"
@@ -403,8 +403,8 @@ libchallenger_plugin_db_postgres_init (void *cls)
= &CH_PG_validation_get;
plugin->info_get_grant
= &CH_PG_info_get_grant;
- plugin->auth_add_grant
- = &CH_PG_auth_add_grant;
+ plugin->token_add_grant
+ = &CH_PG_token_add_grant;
return plugin;
}
diff --git a/src/include/challenger_database_plugin.h b/src/include/challenger_database_plugin.h
@@ -335,11 +335,11 @@ struct CHALLENGER_DatabasePlugin
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
- (*auth_add_grant)(void *cls,
- const struct CHALLENGER_ValidationNonceP *nonce,
- const struct CHALLENGER_AccessTokenP *grant,
- struct GNUNET_TIME_Relative grant_expiration,
- struct GNUNET_TIME_Relative address_expiration);
+ (*token_add_grant)(void *cls,
+ const struct CHALLENGER_ValidationNonceP *nonce,
+ const struct CHALLENGER_AccessTokenP *grant,
+ struct GNUNET_TIME_Relative grant_expiration,
+ struct GNUNET_TIME_Relative address_expiration);
/**