commit 4ce9fb07e98f445c9c97460e780d8c15ca3e1060
parent 80c83d164699ae05f2837275b3a99cb963f00e7a
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 5 Jul 2026 23:30:05 +0200
fix upper-case ID issues in merchant instance creation logic
Diffstat:
1 file changed, 40 insertions(+), 26 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_post-management-instances.c b/src/backend/taler-merchant-httpd_post-management-instances.c
@@ -70,13 +70,14 @@ post_instances (const struct TMH_RequestHandler *rh,
struct TMH_WireMethod *wm_tail = NULL;
const json_t *jauth;
const char *iphone = NULL;
+ char *id_lower;
bool no_pay_delay;
bool no_refund_delay;
bool no_transfer_delay;
bool no_rounding_interval;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("id",
- (const char **) &is.id),
+ TALER_JSON_spec_slug ("id",
+ (const char **) &is.id),
GNUNET_JSON_spec_string ("name",
(const char **) &is.name),
GNUNET_JSON_spec_mark_optional (
@@ -289,17 +290,21 @@ post_instances (const struct TMH_RequestHandler *rh,
"logo");
}
+ id_lower = GNUNET_STRINGS_utf8_tolower (is.id);
{
/* Test if an instance of this id is known */
struct TMH_MerchantInstance *mi;
- mi = TMH_lookup_instance (is.id);
+ mi = TMH_lookup_instance (id_lower);
if (NULL != mi)
{
+ enum MHD_Result ret;
+
if (mi->deleted)
{
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone);
+ GNUNET_free (id_lower);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_CONFLICT,
@@ -308,7 +313,7 @@ post_instances (const struct TMH_RequestHandler *rh,
}
/* Check for idempotency */
if ( (0 == strcmp (mi->settings.id,
- is.id)) &&
+ id_lower)) &&
(0 == strcmp (mi->settings.name,
is.name)) &&
((mi->settings.email == is.email) ||
@@ -348,6 +353,7 @@ post_instances (const struct TMH_RequestHandler *rh,
{
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone);
+ GNUNET_free (id_lower);
return TALER_MHD_reply_static (connection,
MHD_HTTP_NO_CONTENT,
NULL,
@@ -356,10 +362,12 @@ post_instances (const struct TMH_RequestHandler *rh,
}
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
- is.id);
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
+ id_lower);
+ GNUNET_free (id_lower);
+ return ret;
}
}
@@ -374,6 +382,7 @@ post_instances (const struct TMH_RequestHandler *rh,
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone); /* does nothing... */
+ GNUNET_free (id_lower);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MISSING,
@@ -386,6 +395,7 @@ post_instances (const struct TMH_RequestHandler *rh,
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone);
+ GNUNET_free (id_lower);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MISSING,
@@ -400,7 +410,7 @@ post_instances (const struct TMH_RequestHandler *rh,
case TMH_TCS_SMS:
is.phone_validated = true;
ret = TMH_mfa_challenges_do (hc,
- is.id,
+ id_lower,
TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
true,
TALER_MERCHANT_MFA_CHANNEL_SMS,
@@ -410,7 +420,7 @@ post_instances (const struct TMH_RequestHandler *rh,
case TMH_TCS_EMAIL:
is.email_validated = true;
ret = TMH_mfa_challenges_do (hc,
- is.id,
+ id_lower,
TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
true,
TALER_MERCHANT_MFA_CHANNEL_EMAIL,
@@ -421,7 +431,7 @@ post_instances (const struct TMH_RequestHandler *rh,
is.phone_validated = true;
is.email_validated = true;
ret = TMH_mfa_challenges_do (hc,
- is.id,
+ id_lower,
TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
true,
TALER_MERCHANT_MFA_CHANNEL_EMAIL,
@@ -435,6 +445,7 @@ post_instances (const struct TMH_RequestHandler *rh,
{
GNUNET_JSON_parse_free (spec);
GNUNET_free (is.phone);
+ GNUNET_free (id_lower);
return (GNUNET_NO == ret)
? MHD_YES
: MHD_NO;
@@ -470,7 +481,7 @@ post_instances (const struct TMH_RequestHandler *rh,
mi->settings = is;
mi->settings.address = json_incref (mi->settings.address);
mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction);
- mi->settings.id = GNUNET_STRINGS_utf8_tolower (is.id);
+ mi->settings.id = id_lower;
mi->settings.name = GNUNET_strdup (is.name);
if (NULL != is.email)
mi->settings.email = GNUNET_strdup (is.email);
@@ -495,10 +506,11 @@ post_instances (const struct TMH_RequestHandler *rh,
mi->rc = 1;
TMH_instance_decref (mi);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_START_FAILED,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_START_FAILED,
+ NULL);
}
qs = TALER_MERCHANTDB_insert_instance (TMH_db,
&mi->merchant_pub,
@@ -513,10 +525,11 @@ post_instances (const struct TMH_RequestHandler *rh,
TALER_MERCHANTDB_rollback (TMH_db);
GNUNET_break (0);
- ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- is.id);
+ ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_instance");
mi->rc = 1;
TMH_instance_decref (mi);
GNUNET_JSON_parse_free (spec);
@@ -530,10 +543,11 @@ post_instances (const struct TMH_RequestHandler *rh,
TALER_MERCHANTDB_rollback (TMH_db);
GNUNET_break (0);
- ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
- is.id);
+ ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
+ id_lower);
mi->rc = 1;
TMH_instance_decref (mi);
GNUNET_JSON_parse_free (spec);
@@ -581,7 +595,7 @@ retry:
enum GNUNET_DB_QueryStatus qs;
qs = TALER_MERCHANTDB_set_instance (TMH_db,
- is.id);
+ id_lower);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
@@ -621,7 +635,7 @@ retry:
expiration_time
= GNUNET_TIME_relative_to_timestamp (login_token_expiration);
qs = TALER_MERCHANTDB_insert_login_token (TMH_db,
- is.id,
+ id_lower,
&btoken,
GNUNET_TIME_timestamp_get (),
expiration_time,