exchange

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

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 */