exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 55824365b87f548765e3ef2bacddaf33995a5d2a
parent e550e7e1fb17d3a140ccd156ebcaeae563751e90
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 22 Jun 2025 13:48:38 +0200

add 'Cache-control: no-store' by default (fixes #9723)

Diffstat:
Msrc/exchange/taler-exchange-httpd.c | 6++++--
Msrc/exchange/taler-exchange-httpd_aml-decision.c | 3++-
Msrc/exchange/taler-exchange-httpd_keys.c | 3++-
Msrc/exchange/taler-exchange-httpd_kyc-info.c | 3++-
Msrc/exchange/taler-exchange-httpd_kyc-upload.c | 3++-
Msrc/include/taler/taler_mhd2_lib.h | 7++++++-
Msrc/include/taler/taler_mhd_lib.h | 7++++++-
Msrc/kyclogic/plugin_kyclogic_persona.c | 6++++--
Msrc/kyclogic/taler-exchange-helper-sanctions-dummy.c | 4----
Msrc/mhd/Makefile.am | 2+-
Msrc/mhd/mhd2_legal.c | 6++++--
Msrc/mhd/mhd2_responses.c | 23+++++++++++++++++------
Msrc/mhd/mhd_legal.c | 6++++--
Msrc/mhd/mhd_responses.c | 23+++++++++++++++++------
14 files changed, 71 insertions(+), 31 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c @@ -1225,7 +1225,8 @@ handler_seed (struct TEH_RequestContext *rc, resp = MHD_create_response_from_buffer (SEED_SIZE, body, MHD_RESPMEM_MUST_FREE); - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + false); ret = MHD_queue_response (rc->connection, MHD_HTTP_OK, resp); @@ -1534,7 +1535,8 @@ toplevel_redirect (struct TEH_RequestContext *rc, GNUNET_break (0); return MHD_NO; } - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + true); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c @@ -153,7 +153,8 @@ aml_trigger_callback ( adc->response = MHD_create_response_from_buffer_static ( 0, ""); - TALER_MHD_add_global_headers (adc->response); + TALER_MHD_add_global_headers (adc->response, + true); } GNUNET_assert (NULL != adc->response); diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c @@ -2290,7 +2290,8 @@ setup_general_response_headers (void *cls, struct TEH_KeyStateHandle *ksh = cls; char dat[128]; - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + true); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, diff --git a/src/exchange/taler-exchange-httpd_kyc-info.c b/src/exchange/taler-exchange-httpd_kyc-info.c @@ -656,7 +656,8 @@ current_rules_cb ( NULL, MHD_RESPMEM_PERSISTENT); add_nocache_header (resp); - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + false); GNUNET_break (MHD_YES == MHD_add_response_header (resp, MHD_HTTP_HEADER_ETAG, diff --git a/src/exchange/taler-exchange-httpd_kyc-upload.c b/src/exchange/taler-exchange-httpd_kyc-upload.c @@ -170,7 +170,8 @@ aml_trigger_callback ( 0, "" ); - TALER_MHD_add_global_headers (uc->response); + TALER_MHD_add_global_headers (uc->response, + true); } MHD_resume_connection (uc->rc->connection); diff --git a/src/include/taler/taler_mhd2_lib.h b/src/include/taler/taler_mhd2_lib.h @@ -104,9 +104,14 @@ TALER_MHD2_setup (enum TALER_MHD2_GlobalOptions go); * if we want to always close connections. * * @param response response to modify + * @param allow_store set to true to NOT add a "Cache-Control" + * directive that prevents caches and browsers from storing the data; + * if false, we set "Cache-Control: no-store" (privacy by default); + * set to true if the response contains no personal data */ void -TALER_MHD2_add_global_headers (struct MHD_Response *response); +TALER_MHD2_add_global_headers (struct MHD_Response *response, + bool allow_store); /** diff --git a/src/include/taler/taler_mhd_lib.h b/src/include/taler/taler_mhd_lib.h @@ -113,9 +113,14 @@ TALER_MHD_setup (enum TALER_MHD_GlobalOptions go); * if we want to always close connections. * * @param response response to modify + * @param allow_store set to true to NOT add a "Cache-Control" + * directive that prevents caches and browsers from storing the data; + * if false, we set "Cache-Control: no-store" (privacy by default); + * set to true if the response contains no personal data */ void -TALER_MHD_add_global_headers (struct MHD_Response *response); +TALER_MHD_add_global_headers (struct MHD_Response *response, + bool allow_store); /** diff --git a/src/kyclogic/plugin_kyclogic_persona.c b/src/kyclogic/plugin_kyclogic_persona.c @@ -1091,7 +1091,8 @@ proof_post_conversion_cb (void *cls, MHD_add_response_header (resp, MHD_HTTP_HEADER_LOCATION, ph->pd->post_kyc_redirect_url)); - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + false); ph->cb (ph->cb_cls, TALER_KYCLOGIC_STATUS_SUCCESS, ph->pd->section, @@ -1579,7 +1580,8 @@ webhook_generic_reply (struct TALER_KYCLOGIC_WebhookHandle *wh, expiration = GNUNET_TIME_UNIT_ZERO_ABS; resp = MHD_create_response_from_buffer_static (0, ""); - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + true); wh->cb (wh->cb_cls, wh->process_row, &wh->h_payto, diff --git a/src/kyclogic/taler-exchange-helper-sanctions-dummy.c b/src/kyclogic/taler-exchange-helper-sanctions-dummy.c @@ -47,10 +47,6 @@ main (int argc, JSON_DISABLE_EOF_CHECK, &err))) { - struct GNUNET_TIME_Timestamp expiration - = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS)); - if (! json_is_object (input)) { json_decref (input); diff --git a/src/mhd/Makefile.am b/src/mhd/Makefile.am @@ -18,7 +18,7 @@ libtalermhd_la_SOURCES = \ mhd_run.c \ mhd_spa.c libtalermhd_la_LDFLAGS = \ - -version-info 6:0:0 \ + -version-info 7:0:0 \ -no-undefined libtalermhd_la_LIBADD = \ $(top_builddir)/src/json/libtalerjson.la \ diff --git a/src/mhd/mhd2_legal.c b/src/mhd/mhd2_legal.c @@ -257,7 +257,8 @@ TALER_MHD2_reply_legal (struct MHD_Request *request, MHD_RESPONSE_SET_OPTIONS ( resp, MHD_R_OPTION_HEAD_ONLY_RESPONSE (true))); - TALER_MHD2_add_global_headers (resp); + TALER_MHD2_add_global_headers (resp, + true); GNUNET_break (MHD_SC_OK == MHD_response_add_header (resp, MHD_HTTP_HEADER_EXPIRES, @@ -310,7 +311,8 @@ return_t: t->terms_size, (void *) t->terms); } - TALER_MHD2_add_global_headers (resp); + TALER_MHD2_add_global_headers (resp, + true); GNUNET_break (MHD_SC_OK == MHD_response_add_header (resp, MHD_HTTP_HEADER_EXPIRES, diff --git a/src/mhd/mhd2_responses.c b/src/mhd/mhd2_responses.c @@ -40,7 +40,8 @@ TALER_MHD2_setup (enum TALER_MHD2_GlobalOptions go) void -TALER_MHD2_add_global_headers (struct MHD_Response *response) +TALER_MHD2_add_global_headers (struct MHD_Response *response, + bool allow_store) { if (0 != (TM_go & TALER_MHD2_GO_FORCE_CONNECTION_CLOSE)) GNUNET_break (MHD_SC_OK == @@ -58,6 +59,11 @@ TALER_MHD2_add_global_headers (struct MHD_Response *response) /* Not available as MHD constant yet */ "Access-Control-Expose-Headers", "*")); + if (! allow_store) + GNUNET_break (MHD_SC_OK == + MHD_response_add_header (response, + MHD_HTTP_HEADER_CACHE_CONTROL, + "no-store")); } @@ -151,7 +157,8 @@ TALER_MHD2_make_json (enum MHD_HTTP_StatusCode sc, GNUNET_break (0); return NULL; } - TALER_MHD2_add_global_headers (response); + TALER_MHD2_add_global_headers (response, + false); GNUNET_break (MHD_SC_OK == MHD_response_add_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -214,7 +221,8 @@ TALER_MHD2_reply_json (struct MHD_Request *request, GNUNET_break (0); return NULL; } - TALER_MHD2_add_global_headers (response); + TALER_MHD2_add_global_headers (response, + false); GNUNET_break (MHD_SC_OK == MHD_response_add_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -263,7 +271,8 @@ TALER_MHD2_reply_cors_preflight (struct MHD_Request *request) return NULL; /* This adds the Access-Control-Allow-Origin header. * All endpoints of the exchange allow CORS. */ - TALER_MHD2_add_global_headers (response); + TALER_MHD2_add_global_headers (response, + true); GNUNET_break (MHD_SC_OK == MHD_response_add_header (response, /* Not available as MHD constant yet */ @@ -356,7 +365,8 @@ TALER_MHD2_reply_agpl (struct MHD_Request *request, GNUNET_break (0); return MHD_NO; } - TALER_MHD2_add_global_headers (response); + TALER_MHD2_add_global_headers (response, + true); GNUNET_break (MHD_SC_OK == MHD_response_add_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -392,7 +402,8 @@ TALER_MHD2_reply_static (struct MHD_Request *request, GNUNET_break (0); return NULL; } - TALER_MHD2_add_global_headers (response); + TALER_MHD2_add_global_headers (response, + true); if (NULL != mime_type) GNUNET_break (MHD_SC_OK == MHD_response_add_header (response, diff --git a/src/mhd/mhd_legal.c b/src/mhd/mhd_legal.c @@ -250,7 +250,8 @@ TALER_MHD_reply_legal (struct MHD_Connection *conn, resp = MHD_create_response_from_buffer (0, NULL, MHD_RESPMEM_PERSISTENT); - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + true); GNUNET_break (MHD_YES == MHD_add_response_header (resp, MHD_HTTP_HEADER_EXPIRES, @@ -303,7 +304,8 @@ return_t: (void *) t->terms, MHD_RESPMEM_PERSISTENT); } - TALER_MHD_add_global_headers (resp); + TALER_MHD_add_global_headers (resp, + true); GNUNET_break (MHD_YES == MHD_add_response_header (resp, MHD_HTTP_HEADER_EXPIRES, diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c @@ -40,7 +40,8 @@ TALER_MHD_setup (enum TALER_MHD_GlobalOptions go) void -TALER_MHD_add_global_headers (struct MHD_Response *response) +TALER_MHD_add_global_headers (struct MHD_Response *response, + bool allow_store) { if (0 != (TM_go & TALER_MHD_GO_FORCE_CONNECTION_CLOSE)) GNUNET_break (MHD_YES == @@ -58,6 +59,11 @@ TALER_MHD_add_global_headers (struct MHD_Response *response) /* Not available as MHD constant yet */ "Access-Control-Expose-Headers", "*")); + if (! allow_store) + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_CACHE_CONTROL, + "no-store")); } @@ -144,7 +150,8 @@ TALER_MHD_make_json (const json_t *json) GNUNET_break (0); return NULL; } - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + false); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -204,7 +211,8 @@ TALER_MHD_reply_json (struct MHD_Connection *connection, GNUNET_break (0); return MHD_NO; } - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + false); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -262,7 +270,8 @@ TALER_MHD_reply_cors_preflight (struct MHD_Connection *connection) return MHD_NO; /* This adds the Access-Control-Allow-Origin header. * All endpoints of the exchange allow CORS. */ - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + true); GNUNET_break (MHD_YES == MHD_add_response_header (response, /* Not available as MHD constant yet */ @@ -359,7 +368,8 @@ TALER_MHD_reply_agpl (struct MHD_Connection *connection, GNUNET_break (0); return MHD_NO; } - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + true); GNUNET_break (MHD_YES == MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, @@ -403,7 +413,8 @@ TALER_MHD_reply_static (struct MHD_Connection *connection, GNUNET_break (0); return MHD_NO; } - TALER_MHD_add_global_headers (response); + TALER_MHD_add_global_headers (response, + true); if (NULL != mime_type) GNUNET_break (MHD_YES == MHD_add_response_header (response,