commit b0902b5efd07d766767f7645a37ad11b93a810db
parent 756c2ba769ab71933348876e03d34375a02c1644
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Sun, 3 Aug 2025 01:39:40 +0200
add bearer token logic
Diffstat:
10 files changed, 188 insertions(+), 61 deletions(-)
diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c
@@ -126,6 +126,11 @@ char *DH_domain;
char *DH_base_url;
/**
+ * Our administrative bearer token.
+ */
+static char *admin_bearer;
+
+/**
* Default timeout in seconds for HTTP requests.
*/
static unsigned int connection_timeout = 30;
@@ -279,6 +284,28 @@ proceed_with_handler (struct DH_RequestContext *rc,
json_t *root = NULL;
MHD_RESULT ret;
+ if ( (rh->needs_authorization) &&
+ (NULL != admin_bearer) )
+ {
+ const char *ah;
+
+ ah = MHD_lookup_connection_value (rc->connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_AUTHORIZATION);
+ if ( (NULL == ah) ||
+ (0 != strncasecmp (ah,
+ "Bearer ",
+ strlen ("Bearer "))) ||
+ (0 != strcmp (ah + strlen ("Bearer "),
+ admin_bearer)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_GENERIC_TOKEN_PERMISSION_INSUFFICIENT,
+ "authorization required");
+ }
+ }
/* We do check for "ulen" here, because we'll later stack-allocate a buffer
of that size and don't want to enable malicious clients to cause us
huge stack allocations. */
@@ -395,11 +422,8 @@ handle_get_charities (struct DH_RequestContext *rc,
{
return DH_handler_charities_get (rc);
}
- else
- {
- return DH_handler_charity_get (rc,
- &args[0]);
- }
+ return DH_handler_charity_get (rc,
+ &args[0]);
}
@@ -457,20 +481,23 @@ handle_mhd_request (void *cls,
.method = MHD_HTTP_METHOD_GET,
.handler.get = &handle_get_charities,
.nargs = 1,
- .nargs_is_upper_bound = true
+ .nargs_is_upper_bound = true,
+ .needs_authorization = true
},
/* POST charities */
{
.url = "charities",
.method = MHD_HTTP_METHOD_POST,
- .handler.post = &DH_handler_charity_post
+ .handler.post = &DH_handler_charity_post,
+ .needs_authorization = true
},
/* DELETE charities */
{
.url = "charities",
.method = MHD_HTTP_METHOD_DELETE,
.handler.delete = &DH_handler_charity_delete,
- .nargs = 1
+ .nargs = 1,
+ .needs_authorization = true
},
/* POST get csr values*/
{
@@ -779,6 +806,16 @@ donau_serve_process_config (void)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (DH_cfg,
"donau",
+ "ADMIN_BEARER_TOKEN",
+ &admin_bearer))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "donau",
+ "ADMIN_BEARER_TOKEN");
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (DH_cfg,
+ "donau",
"BASE_URL",
&DH_base_url))
{
diff --git a/src/donau/donau-httpd.h b/src/donau/donau-httpd.h
@@ -174,6 +174,11 @@ struct DH_RequestHandler
const char *method;
/**
+ * True if HTTP authorization via Bearer token is required.
+ */
+ bool needs_authorization;
+
+ /**
* Callbacks for handling of the request. Which one is used
* depends on @e method.
*/
diff --git a/src/donau/donau.conf b/src/donau/donau.conf
@@ -2,6 +2,9 @@
#
[donau]
+# Bearer access token required to manage charities.
+#ADMIN_BEARER_TOKEN = "secret-token:password"
+
# How many digits does the currency use by default on displays.
# Hint provided to wallets. Should be 2 for EUR/USD/CHF,
# and 0 for JPY. Default is 2 as that is most common.
diff --git a/src/donaudb/test_donaudb.c b/src/donaudb/test_donaudb.c
@@ -176,12 +176,12 @@ run (void *cls)
struct DONAU_DonationReceiptHashP h_receipt;
struct TALER_Amount amount_receipts;
bool smaller_than_max_per_year;
- struct DONAUDB_IssuedReceiptsMetaData ir_meta;
+ // struct DONAUDB_IssuedReceiptsMetaData ir_meta;
// Submitted receipts information
- struct DONAU_HashDonorTaxId h_donor_tax_id;
- size_t num_dr = 1;
- struct DONAU_DonationReceipt donation_receipts[num_dr];
+ // struct DONAU_HashDonorTaxId h_donor_tax_id;
+ // size_t num_dr = 1;
+ // struct DONAU_DonationReceipt donation_receipts[num_dr];
if (NULL ==
(plugin = DONAUDB_plugin_load (cfg)))
diff --git a/src/lib/donau_api_charities_get.c b/src/lib/donau_api_charities_get.c
@@ -169,6 +169,11 @@ handle_charities_get_finished (void *cls,
gcresp.hr.ec = TALER_JSON_get_error_code (j);
gcresp.hr.hint = TALER_JSON_get_error_hint (j);
break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Nothing really to verify */
+ gcresp.hr.ec = TALER_JSON_get_error_code (j);
+ gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
@@ -245,6 +250,23 @@ DONAU_charities_get (
eh,
&handle_charities_get_finished,
cgh);
+ GNUNET_assert (NULL != cgh->job);
+ if (NULL != bearer)
+ {
+ struct curl_slist *auth;
+ char *hdr;
+
+ GNUNET_asprintf (&hdr,
+ "%s: Bearer %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ bearer->token);
+ auth = curl_slist_append (NULL,
+ hdr);
+ GNUNET_free (hdr);
+ GNUNET_CURL_extend_headers (cgh->job,
+ auth);
+ curl_slist_free_all (auth);
+ }
return cgh;
}
diff --git a/src/lib/donau_api_charity_delete.c b/src/lib/donau_api_charity_delete.c
@@ -193,6 +193,23 @@ DONAU_charity_delete (
eh,
&handle_charity_delete_finished,
cdh);
+ GNUNET_assert (NULL != cdh->job);
+ if (NULL != bearer)
+ {
+ struct curl_slist *auth;
+ char *hdr;
+
+ GNUNET_asprintf (&hdr,
+ "%s: Bearer %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ bearer->token);
+ auth = curl_slist_append (NULL,
+ hdr);
+ GNUNET_free (hdr);
+ GNUNET_CURL_extend_headers (cdh->job,
+ auth);
+ curl_slist_free_all (auth);
+ }
return cdh;
}
diff --git a/src/lib/donau_api_charity_get.c b/src/lib/donau_api_charity_get.c
@@ -161,6 +161,11 @@ handle_charity_get_finished (void *cls,
gcresp.hr.ec = TALER_JSON_get_error_code (j);
gcresp.hr.hint = TALER_JSON_get_error_hint (j);
break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Nothing really to verify */
+ gcresp.hr.ec = TALER_JSON_get_error_code (j);
+ gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
@@ -243,6 +248,23 @@ DONAU_charity_get (
eh,
&handle_charity_get_finished,
cgh);
+ GNUNET_assert (NULL != cgh->job);
+ if (NULL != bearer)
+ {
+ struct curl_slist *auth;
+ char *hdr;
+
+ GNUNET_asprintf (&hdr,
+ "%s: Bearer %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ bearer->token);
+ auth = curl_slist_append (NULL,
+ hdr);
+ GNUNET_free (hdr);
+ GNUNET_CURL_extend_headers (cgh->job,
+ auth);
+ curl_slist_free_all (auth);
+ }
return cgh;
}
diff --git a/src/lib/donau_api_charity_post.c b/src/lib/donau_api_charity_post.c
@@ -215,6 +215,23 @@ DONAU_charity_post (
cph->post_ctx.headers,
&handle_charity_post_finished,
cph);
+ GNUNET_assert (NULL != cph->job);
+ if (NULL != bearer)
+ {
+ struct curl_slist *auth;
+ char *hdr;
+
+ GNUNET_asprintf (&hdr,
+ "%s: Bearer %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ bearer->token);
+ auth = curl_slist_append (NULL,
+ hdr);
+ GNUNET_free (hdr);
+ GNUNET_CURL_extend_headers (cph->job,
+ auth);
+ curl_slist_free_all (auth);
+ }
return cph;
}
diff --git a/src/testing/test_donau_api.c b/src/testing/test_donau_api.c
@@ -60,59 +60,58 @@ static void
run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
- const struct DONAU_BearerToken bearer = {
- .token = NULL
+ const static struct DONAU_BearerToken bearer = {
+ .token = "secret-token:secret"
};
- {
- struct TALER_TESTING_Command commands[] = {
- TALER_TESTING_cmd_system_start ("start-donau",
- config_file,
- "-D",
- "NULL"),
- TALER_TESTING_cmd_get_donau ("get-donau",
- cred.cfg,
- true),
- TALER_TESTING_cmd_charity_post ("post-charity",
- "example",
- "example.com",
- "EUR:50", // max_per_year
- "EUR:0", // receipts_to_date
- 2025, // current year
- &bearer,
- MHD_HTTP_CREATED),
- TALER_TESTING_cmd_charity_get ("get-charity-by-id",
- "post-charity", // cmd trait reference
+ struct TALER_TESTING_Command commands[] = {
+ TALER_TESTING_cmd_system_start ("start-donau",
+ config_file,
+ "-D",
+ "NULL"),
+ TALER_TESTING_cmd_get_donau ("get-donau",
+ cred.cfg,
+ true),
+ TALER_TESTING_cmd_charity_post ("post-charity",
+ "example",
+ "example.com",
+ "EUR:50", // max_per_year
+ "EUR:0", // receipts_to_date
+ 2025, // current year
+ &bearer,
+ MHD_HTTP_CREATED),
+ TALER_TESTING_cmd_charity_get ("get-charity-by-id",
+ "post-charity", // cmd trait reference
+ &bearer,
+ MHD_HTTP_OK),
+ TALER_TESTING_cmd_charities_get ("get-charities",
&bearer,
MHD_HTTP_OK),
- TALER_TESTING_cmd_charities_get ("get-charities",
- &bearer,
- MHD_HTTP_OK),
- // FIXME: CSR signatures
- TALER_TESTING_cmd_issue_receipts ("issue-receipts",
- "post-charity",
- uses_cs,
- 2025,
- "7560001010000", // tax id
- "1234", // salt for tax id hash
- MHD_HTTP_CREATED),
- TALER_TESTING_cmd_submit_receipts ("submit-receipts",
- "issue-receipts", // cmd trait reference
- 2025,
- MHD_HTTP_CREATED),
- TALER_TESTING_cmd_donation_statement_get ("donation-statement",
- 2025,
- MHD_HTTP_OK),
- TALER_TESTING_cmd_charity_delete ("delete-charity",
- "post-charity", // cmd trait reference
- &bearer,
- MHD_HTTP_NO_CONTENT),
- /* End the suite. */
- TALER_TESTING_cmd_end ()
- };
+ // FIXME: CSR signatures
+ TALER_TESTING_cmd_issue_receipts ("issue-receipts",
+ "post-charity",
+ uses_cs,
+ 2025,
+ "7560001010000", // tax id
+ "1234", // salt for tax id hash
+ MHD_HTTP_CREATED),
+ TALER_TESTING_cmd_submit_receipts ("submit-receipts",
+ "issue-receipts", // cmd trait reference
+ 2025,
+ MHD_HTTP_CREATED),
+ TALER_TESTING_cmd_donation_statement_get ("donation-statement",
+ 2025,
+ MHD_HTTP_OK),
+ TALER_TESTING_cmd_charity_delete ("delete-charity",
+ "post-charity", // cmd trait reference
+ &bearer,
+ MHD_HTTP_NO_CONTENT),
+ /* End the suite. */
+ TALER_TESTING_cmd_end ()
+ };
- TALER_TESTING_run (is,
- commands);
- }
+ (void) cls;
+ TALER_TESTING_run (is,
+ commands);
}
diff --git a/src/testing/test_donau_api.conf b/src/testing/test_donau_api.conf
@@ -6,6 +6,11 @@ TALER_TEST_HOME = test_donau_api_home/
DONAU_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/donau-system-runtime/
[donau]
+
+# Bearer access token required to manage charities.
+ADMIN_BEARER_TOKEN = "secret-token:secret"
+
+
CURRENCY = EUR
CURRENCY_ROUND_UNIT = EUR:0.01
TERMS_ETAG = tos