taler-exchange-httpd_responses.c (12334B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2023 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file taler-exchange-httpd_responses.c 18 * @brief API for generating generic replies of the exchange; these 19 * functions are called TEH_RESPONSE_reply_ and they generate 20 * and queue MHD response objects for a given connection. 21 * @author Florian Dold 22 * @author Benedikt Mueller 23 * @author Christian Grothoff 24 */ 25 #include <gnunet/gnunet_json_lib.h> 26 #include <microhttpd.h> 27 #include <zlib.h> 28 #include "taler-exchange-httpd_responses.h" 29 #include "taler/taler_util.h" 30 #include "taler/taler_json_lib.h" 31 #include "taler/taler_mhd_lib.h" 32 #include "taler-exchange-httpd_get-keys.h" 33 34 35 enum MHD_Result 36 TEH_RESPONSE_reply_unknown_denom_pub_hash ( 37 struct MHD_Connection *connection, 38 const struct TALER_DenominationHashP *dph) 39 { 40 struct TALER_ExchangePublicKeyP epub; 41 struct TALER_ExchangeSignatureP esig; 42 struct GNUNET_TIME_Timestamp now; 43 enum TALER_ErrorCode ec; 44 45 now = GNUNET_TIME_timestamp_get (); 46 ec = TALER_exchange_online_denomination_unknown_sign ( 47 &TEH_keys_exchange_sign_, 48 now, 49 dph, 50 &epub, 51 &esig); 52 if (TALER_EC_NONE != ec) 53 { 54 GNUNET_break (0); 55 return TALER_MHD_reply_with_error (connection, 56 MHD_HTTP_INTERNAL_SERVER_ERROR, 57 ec, 58 NULL); 59 } 60 return TALER_MHD_REPLY_JSON_PACK ( 61 connection, 62 MHD_HTTP_NOT_FOUND, 63 TALER_JSON_pack_ec (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN), 64 GNUNET_JSON_pack_timestamp ("timestamp", 65 now), 66 GNUNET_JSON_pack_data_auto ("exchange_pub", 67 &epub), 68 GNUNET_JSON_pack_data_auto ("exchange_sig", 69 &esig), 70 GNUNET_JSON_pack_data_auto ("h_denom_pub", 71 dph)); 72 } 73 74 75 enum MHD_Result 76 TEH_RESPONSE_reply_expired_denom_pub_hash ( 77 struct MHD_Connection *connection, 78 const struct TALER_DenominationHashP *dph, 79 enum TALER_ErrorCode ec, 80 const char *oper) 81 { 82 struct TALER_ExchangePublicKeyP epub; 83 struct TALER_ExchangeSignatureP esig; 84 enum TALER_ErrorCode ecr; 85 struct GNUNET_TIME_Timestamp now 86 = GNUNET_TIME_timestamp_get (); 87 88 GNUNET_assert (NULL != oper); 89 ecr = TALER_exchange_online_denomination_expired_sign ( 90 &TEH_keys_exchange_sign_, 91 now, 92 dph, 93 oper, 94 &epub, 95 &esig); 96 if (TALER_EC_NONE != ecr) 97 { 98 GNUNET_break (0); 99 return TALER_MHD_reply_with_error (connection, 100 MHD_HTTP_INTERNAL_SERVER_ERROR, 101 ec, 102 NULL); 103 } 104 return TALER_MHD_REPLY_JSON_PACK ( 105 connection, 106 MHD_HTTP_GONE, 107 TALER_JSON_pack_ec (ec), 108 GNUNET_JSON_pack_string ("oper", 109 oper), 110 GNUNET_JSON_pack_timestamp ("timestamp", 111 now), 112 GNUNET_JSON_pack_data_auto ("exchange_pub", 113 &epub), 114 GNUNET_JSON_pack_data_auto ("exchange_sig", 115 &esig), 116 GNUNET_JSON_pack_data_auto ("h_denom_pub", 117 dph)); 118 } 119 120 121 enum MHD_Result 122 TEH_RESPONSE_reply_invalid_denom_cipher_for_operation ( 123 struct MHD_Connection *connection, 124 const struct TALER_DenominationHashP *dph) 125 { 126 struct TALER_ExchangePublicKeyP epub; 127 struct TALER_ExchangeSignatureP esig; 128 struct GNUNET_TIME_Timestamp now; 129 enum TALER_ErrorCode ec; 130 131 now = GNUNET_TIME_timestamp_get (); 132 ec = TALER_exchange_online_denomination_unknown_sign ( 133 &TEH_keys_exchange_sign_, 134 now, 135 dph, 136 &epub, 137 &esig); 138 if (TALER_EC_NONE != ec) 139 { 140 GNUNET_break (0); 141 return TALER_MHD_reply_with_error (connection, 142 MHD_HTTP_INTERNAL_SERVER_ERROR, 143 ec, 144 NULL); 145 } 146 return TALER_MHD_REPLY_JSON_PACK ( 147 connection, 148 MHD_HTTP_NOT_FOUND, 149 TALER_JSON_pack_ec ( 150 TALER_EC_EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION), 151 GNUNET_JSON_pack_timestamp ("timestamp", 152 now), 153 GNUNET_JSON_pack_data_auto ("exchange_pub", 154 &epub), 155 GNUNET_JSON_pack_data_auto ("exchange_sig", 156 &esig), 157 GNUNET_JSON_pack_data_auto ("h_denom_pub", 158 dph)); 159 } 160 161 162 enum MHD_Result 163 TEH_RESPONSE_reply_coin_insufficient_funds ( 164 struct MHD_Connection *connection, 165 enum TALER_ErrorCode ec, 166 const struct TALER_DenominationHashP *h_denom_pub, 167 const struct TALER_CoinSpendPublicKeyP *coin_pub) 168 { 169 return TALER_MHD_REPLY_JSON_PACK ( 170 connection, 171 TALER_ErrorCode_get_http_status_safe (ec), 172 TALER_JSON_pack_ec (ec), 173 GNUNET_JSON_pack_data_auto ("coin_pub", 174 coin_pub), 175 // FIXME - #7267: to be kept only for some of the error types! 176 GNUNET_JSON_pack_data_auto ("h_denom_pub", 177 h_denom_pub)); 178 } 179 180 181 enum MHD_Result 182 TEH_RESPONSE_reply_coin_conflicting_contract ( 183 struct MHD_Connection *connection, 184 enum TALER_ErrorCode ec, 185 const struct TALER_MerchantWireHashP *h_wire) 186 { 187 return TALER_MHD_REPLY_JSON_PACK ( 188 connection, 189 TALER_ErrorCode_get_http_status_safe (ec), 190 GNUNET_JSON_pack_data_auto ("h_wire", 191 h_wire), 192 TALER_JSON_pack_ec (ec)); 193 } 194 195 196 enum MHD_Result 197 TEH_RESPONSE_reply_coin_denomination_conflict ( 198 struct MHD_Connection *connection, 199 enum TALER_ErrorCode ec, 200 const struct TALER_CoinSpendPublicKeyP *coin_pub, 201 const struct TALER_DenominationPublicKey *prev_denom_pub, 202 const struct TALER_DenominationSignature *prev_denom_sig) 203 { 204 return TALER_MHD_REPLY_JSON_PACK ( 205 connection, 206 TALER_ErrorCode_get_http_status_safe (ec), 207 TALER_JSON_pack_ec (ec), 208 GNUNET_JSON_pack_data_auto ("coin_pub", 209 coin_pub), 210 TALER_JSON_pack_denom_pub ("prev_denom_pub", 211 prev_denom_pub), 212 TALER_JSON_pack_denom_sig ("prev_denom_sig", 213 prev_denom_sig) 214 ); 215 216 } 217 218 219 enum MHD_Result 220 TEH_RESPONSE_reply_coin_age_commitment_conflict ( 221 struct MHD_Connection *connection, 222 enum TALER_ErrorCode ec, 223 enum TALER_EXCHANGEDB_CoinKnownStatus status, 224 const struct TALER_DenominationHashP *h_denom_pub, 225 const struct TALER_CoinSpendPublicKeyP *coin_pub, 226 const struct TALER_AgeCommitmentHashP *h_age_commitment) 227 { 228 const char *conflict_detail; 229 230 switch (status) 231 { 232 233 case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL: 234 conflict_detail = "expected NULL age commitment hash"; 235 h_age_commitment = NULL; 236 break; 237 case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL: 238 conflict_detail = "expected non-NULL age commitment hash"; 239 break; 240 case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS: 241 conflict_detail = "expected age commitment hash differs"; 242 break; 243 default: 244 GNUNET_assert (0); 245 } 246 247 return TALER_MHD_REPLY_JSON_PACK ( 248 connection, 249 TALER_ErrorCode_get_http_status_safe (ec), 250 TALER_JSON_pack_ec (ec), 251 GNUNET_JSON_pack_data_auto ("coin_pub", 252 coin_pub), 253 GNUNET_JSON_pack_data_auto ("h_denom_pub", 254 h_denom_pub), 255 GNUNET_JSON_pack_allow_null ( 256 GNUNET_JSON_pack_data_auto ("expected_age_commitment_hash", 257 h_age_commitment)), 258 GNUNET_JSON_pack_string ("conflict_detail", 259 conflict_detail) 260 ); 261 } 262 263 264 enum MHD_Result 265 TEH_RESPONSE_reply_reserve_insufficient_balance ( 266 struct MHD_Connection *connection, 267 enum TALER_ErrorCode ec, 268 const struct TALER_Amount *reserve_balance, 269 const struct TALER_Amount *balance_required, 270 const struct TALER_ReservePublicKeyP *reserve_pub) 271 { 272 return TALER_MHD_REPLY_JSON_PACK ( 273 connection, 274 MHD_HTTP_CONFLICT, 275 TALER_JSON_pack_ec (ec), 276 TALER_JSON_pack_amount ("balance", 277 reserve_balance), 278 TALER_JSON_pack_amount ("requested_amount", 279 balance_required)); 280 } 281 282 283 enum MHD_Result 284 TEH_RESPONSE_reply_reserve_age_restriction_required ( 285 struct MHD_Connection *connection, 286 uint16_t maximum_allowed_age) 287 { 288 return TALER_MHD_REPLY_JSON_PACK ( 289 connection, 290 MHD_HTTP_CONFLICT, 291 TALER_JSON_pack_ec (TALER_EC_EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED), 292 GNUNET_JSON_pack_uint64 ("maximum_allowed_age", 293 maximum_allowed_age)); 294 } 295 296 297 enum MHD_Result 298 TEH_RESPONSE_reply_purse_created ( 299 struct MHD_Connection *connection, 300 struct GNUNET_TIME_Timestamp exchange_timestamp, 301 const struct TALER_Amount *purse_balance, 302 const struct TEH_PurseDetails *pd) 303 { 304 struct TALER_ExchangePublicKeyP pub; 305 struct TALER_ExchangeSignatureP sig; 306 enum TALER_ErrorCode ec; 307 308 if (TALER_EC_NONE != 309 (ec = TALER_exchange_online_purse_created_sign ( 310 &TEH_keys_exchange_sign_, 311 exchange_timestamp, 312 pd->purse_expiration, 313 &pd->target_amount, 314 purse_balance, 315 &pd->purse_pub, 316 &pd->h_contract_terms, 317 &pub, 318 &sig))) 319 { 320 GNUNET_break (0); 321 return TALER_MHD_reply_with_ec (connection, 322 ec, 323 NULL); 324 } 325 return TALER_MHD_REPLY_JSON_PACK ( 326 connection, 327 MHD_HTTP_OK, 328 TALER_JSON_pack_amount ("total_deposited", 329 purse_balance), 330 GNUNET_JSON_pack_timestamp ("exchange_timestamp", 331 exchange_timestamp), 332 GNUNET_JSON_pack_data_auto ("exchange_sig", 333 &sig), 334 GNUNET_JSON_pack_data_auto ("exchange_pub", 335 &pub)); 336 } 337 338 339 enum MHD_Result 340 TEH_RESPONSE_reply_kyc_required ( 341 struct MHD_Connection *connection, 342 const struct TALER_NormalizedPaytoHashP *h_payto, 343 const struct TALER_EXCHANGEDB_KycStatus *kyc, 344 bool bad_kyc_auth) 345 { 346 return TALER_MHD_REPLY_JSON_PACK ( 347 connection, 348 MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, 349 TALER_JSON_pack_ec (TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED), 350 GNUNET_JSON_pack_data_auto ("h_payto", 351 h_payto), 352 GNUNET_JSON_pack_allow_null ( 353 GNUNET_JSON_pack_data_auto ( 354 "account_pub", 355 (kyc->have_account_pub 356 ? &kyc->account_pub 357 : NULL))), 358 GNUNET_JSON_pack_allow_null ( 359 bad_kyc_auth 360 ? GNUNET_JSON_pack_bool ("bad_kyc_auth", 361 bad_kyc_auth) 362 : GNUNET_JSON_pack_string ("bad_kyc_auth", 363 NULL)), 364 GNUNET_JSON_pack_uint64 ("requirement_row", 365 kyc->requirement_row)); 366 } 367 368 369 enum MHD_Result 370 TEH_RESPONSE_reply_not_modified ( 371 struct MHD_Connection *connection, 372 const char *etags, 373 TEH_RESPONSE_SetHeaders cb, 374 void *cb_cls) 375 { 376 enum MHD_Result ret; 377 struct MHD_Response *resp; 378 379 resp = MHD_create_response_from_buffer (0, 380 NULL, 381 MHD_RESPMEM_PERSISTENT); 382 if (NULL != cb) 383 cb (cb_cls, 384 resp); 385 GNUNET_break (MHD_YES == 386 MHD_add_response_header (resp, 387 MHD_HTTP_HEADER_ETAG, 388 etags)); 389 ret = MHD_queue_response (connection, 390 MHD_HTTP_NOT_MODIFIED, 391 resp); 392 GNUNET_break (MHD_YES == ret); 393 MHD_destroy_response (resp); 394 return ret; 395 } 396 397 398 /* end of taler-exchange-httpd_responses.c */