commit 7c29dd278d79fe3b3819ab0fe0172624cb675cf1
parent 356875a4f7393584ad4f90165bfdcf4bd0c69fed
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 20 Apr 2026 15:09:23 +0200
address various FIXMEs
Diffstat:
4 files changed, 98 insertions(+), 68 deletions(-)
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
@@ -12,6 +12,7 @@ bin_PROGRAMS = \
paivana_httpd_SOURCES = \
paivana-httpd.c \
paivana-httpd_cookie.c paivana-httpd_cookie.h \
+ paivana-httpd_helper.c paivana-httpd_helper.h \
paivana-httpd_reverse.c paivana-httpd_reverse.h \
paivana-httpd_pay.c paivana-httpd_pay.h \
paivana_pd.c paivana_pd.h
@@ -19,6 +20,7 @@ paivana_httpd_LDADD = \
$(LIBGCRYPT_LIBS) \
-ltalermerchant \
-ltalermhd \
+ -ltalerutil \
-lgnunetjson \
-lgnunetcurl \
-lgnunetutil \
diff --git a/src/backend/paivana-httpd.c b/src/backend/paivana-httpd.c
@@ -33,6 +33,7 @@
#include <taler/taler_mhd_lib.h>
#include "paivana-httpd.h"
#include "paivana-httpd_cookie.h"
+#include "paivana-httpd_helper.h"
#include "paivana-httpd_pay.h"
#include "paivana-httpd_reverse.h"
#include "paivana_pd.h"
@@ -77,6 +78,8 @@ char *PH_target_server_base_url;
char *PH_merchant_base_url;
+char *PH_base_url;
+
struct GNUNET_CURL_Context *PH_ctx;
@@ -194,36 +197,34 @@ create_response (void *cls,
"Paivana-Cookie");
if (NULL != cookie)
{
- const union MHD_ConnectionInfo *ci;
- const struct sockaddr *ca;
- socklen_t ca_len;
+ void *ca;
+ size_t ca_len;
+ struct GNUNET_Buffer buf;
+ char *website;
bool ok;
- // FIXME: de-duplicate with logic in paivana-httpd_pay.c,
- // and also support getting client address from HTTP
- // headers instead (in case of reverse proxy).
- ci = MHD_get_connection_info (con,
- MHD_CONNECTION_INFO_CLIENT_ADDRESS);
- GNUNET_assert (NULL != ci);
- ca = ci->client_addr;
- switch (ca->sa_family)
+ GNUNET_break (PAIVANA_HTTPD_get_client_address (con,
+ &ca,
+ &ca_len));
+ if (! PAIVANA_HTTPD_get_base_url (con,
+ &buf))
{
- case AF_INET:
- ca_len = sizeof (struct sockaddr_in);
- break;
- case AF_INET6:
- ca_len = sizeof (struct sockaddr_in6);
- break;
- default:
GNUNET_break (0);
- ca_len = 0;
- break;
+ return TALER_MHD_reply_with_error (
+ con,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED,
+ "Host or X-Forwarded-Host required");
}
- /* FIXME: url vs. full path to the website? Which should we use? */
+ GNUNET_buffer_write_str (&buf,
+ url);
+ website = GNUNET_buffer_reap_str (&buf);
ok = PAIVANA_HTTPD_check_cookie (cookie,
- url,
+ website,
ca_len,
ca);
+ GNUNET_free (website);
+ GNUNET_free (ca);
if (! ok)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -327,6 +328,7 @@ do_shutdown (void *cls)
TALER_MHD_daemons_destroy ();
GNUNET_free (PH_target_server_base_url);
GNUNET_free (PH_merchant_base_url);
+ GNUNET_free (PH_base_url);
if (NULL != PH_ctx)
{
GNUNET_CURL_fini (PH_ctx);
@@ -482,6 +484,15 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ if (! TALER_is_web_url (PH_target_server_base_url))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "paivana",
+ "DESTINATION_BASE_URL",
+ "not a web url");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (
c,
@@ -495,6 +506,41 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ if (! TALER_is_web_url (PH_merchant_base_url))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "paivana",
+ "MERCHANT_BACKEND_URL",
+ "not a web url");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (
+ c,
+ "paivana",
+ "BASE_URL",
+ &PH_base_url))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
+ "paivana",
+ "BASE_URL");
+ }
+ if (NULL != PH_base_url)
+ {
+ if (! TALER_is_web_url (PH_base_url))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "paivana",
+ "BASE_URL",
+ "not a web url");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if ('/' == PH_base_url[strlen (PH_base_url) - 1])
+ PH_base_url[strlen (PH_base_url) - 1] = '\0';
+ }
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (
c,
diff --git a/src/backend/paivana-httpd.h b/src/backend/paivana-httpd.h
@@ -48,9 +48,15 @@ extern char *PH_target_server_base_url;
extern char *PH_merchant_base_url;
/**
+ * Base URL of this site as seen by the client. If not set,
+ * we will try to determine it from "X-Forwarded-Host" and
+ * "Host" and "X-Forwarded-Port" headers.
+ */
+extern char *PH_base_url;
+
+/**
* Curl context for making HTTP requests.
*/
extern struct GNUNET_CURL_Context *PH_ctx;
-
#endif
diff --git a/src/backend/paivana-httpd_pay.c b/src/backend/paivana-httpd_pay.c
@@ -23,11 +23,12 @@
* @file paivana-httpd_pay.c
* @brief payment processing logic
*/
-#include <gnunet/gnunet_util_lib.h>
#include <microhttpd.h>
+#include <gnunet/gnunet_util_lib.h>
#include <taler/taler_mhd_lib.h>
#include <taler/taler_error_codes.h>
#include "paivana-httpd_cookie.h"
+#include "paivana-httpd_helper.h"
#include "paivana-httpd_pay.h"
struct PayRequest;
@@ -159,16 +160,14 @@ check_contract (struct PayRequest *ph,
{
struct GNUNET_TIME_Timestamp max_time
= GNUNET_TIME_UNIT_FOREVER_TS;
- const char *regex_s = NULL;
- // FIXME: expand Paivana contract template specifications with
- // these fields!
+ const char *target = NULL;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("website_regex",
- ®ex_s),
+ GNUNET_JSON_spec_string ("fulfillment_url",
+ &target),
NULL),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_timestamp ("max_time",
+ GNUNET_JSON_spec_timestamp ("max_pickup_time",
&max_time),
NULL),
GNUNET_JSON_spec_end ()
@@ -189,28 +188,22 @@ check_contract (struct PayRequest *ph,
eline);
return true;
}
- if (NULL != regex_s)
+ if ( (NULL != target) &&
+ (0 != strcmp (target,
+ ph->website)) )
{
- bool match = true;
-
- // FIXME: check ph->website matches regex.
- // If not: => TALER_EC_PAIVANA_WRONG_ORDER with 409!
- if (! match)
- {
- GNUNET_break_op (0);
- ph->response = TALER_MHD_make_error (TALER_EC_PAIVANA_WRONG_ORDER,
- ph->order_id);
- ph->response_status = MHD_HTTP_CONFLICT;
- return false;
- }
+ GNUNET_break_op (0);
+ ph->response = TALER_MHD_make_error (TALER_EC_PAIVANA_WRONG_ORDER,
+ ph->order_id);
+ ph->response_status = MHD_HTTP_CONFLICT;
+ return false;
}
if (GNUNET_TIME_timestamp_cmp (ph->cur_time,
>,
max_time))
{
GNUNET_break_op (0);
- // FIXME: bad EC! Introduce new one!
- ph->response = TALER_MHD_make_error (TALER_EC_PAIVANA_WRONG_ORDER,
+ ph->response = TALER_MHD_make_error (TALER_EC_PAIVANA_TOO_LATE,
ph->order_id);
ph->response_status = MHD_HTTP_GONE;
return false;
@@ -242,39 +235,22 @@ order_status_cb (struct PayRequest *ph,
}
else
{
- const union MHD_ConnectionInfo *ci;
- const struct sockaddr *ca;
- socklen_t ca_len;
+ void *ca;
+ size_t ca_len;
char *cookie;
struct MHD_Response *resp;
- // FIXME: de-duplicate with logic in paivana-httpd.c,
- // and also support getting client address from HTTP
- // headers instead (in case of reverse proxy).
- ci = MHD_get_connection_info (ph->connection,
- MHD_CONNECTION_INFO_CLIENT_ADDRESS);
- GNUNET_assert (NULL != ci);
- ca = ci->client_addr;
- switch (ca->sa_family)
- {
- case AF_INET:
- ca_len = sizeof (struct sockaddr_in);
- break;
- case AF_INET6:
- ca_len = sizeof (struct sockaddr_in6);
- break;
- default:
- GNUNET_break (0);
- ca_len = 0;
- break;
- }
if (! check_contract (ph,
osr->details.ok.details.paid.contract_terms))
return;
+ GNUNET_break (PAIVANA_HTTPD_get_client_address (ph->connection,
+ &ca,
+ &ca_len));
cookie = PAIVANA_HTTPD_compute_cookie (ph->cur_time,
ph->website,
ca_len,
ca);
+ GNUNET_free (ca);
resp = MHD_create_response_from_buffer (0,
NULL,
MHD_RESPMEM_PERSISTENT);