Line data Source code
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 "taler/platform.h"
26 : #include <gnunet/gnunet_json_lib.h>
27 : #include <microhttpd.h>
28 : #include <zlib.h>
29 : #include "taler-exchange-httpd_responses.h"
30 : #include "taler/taler_exchangedb_plugin.h"
31 : #include "taler/taler_util.h"
32 : #include "taler/taler_json_lib.h"
33 : #include "taler/taler_mhd_lib.h"
34 : #include "taler-exchange-httpd_keys.h"
35 :
36 :
37 : MHD_RESULT
38 0 : TEH_RESPONSE_reply_unknown_denom_pub_hash (
39 : struct MHD_Connection *connection,
40 : const struct TALER_DenominationHashP *dph)
41 : {
42 : struct TALER_ExchangePublicKeyP epub;
43 : struct TALER_ExchangeSignatureP esig;
44 : struct GNUNET_TIME_Timestamp now;
45 : enum TALER_ErrorCode ec;
46 :
47 0 : now = GNUNET_TIME_timestamp_get ();
48 0 : ec = TALER_exchange_online_denomination_unknown_sign (
49 : &TEH_keys_exchange_sign_,
50 : now,
51 : dph,
52 : &epub,
53 : &esig);
54 0 : if (TALER_EC_NONE != ec)
55 : {
56 0 : GNUNET_break (0);
57 0 : return TALER_MHD_reply_with_error (connection,
58 : MHD_HTTP_INTERNAL_SERVER_ERROR,
59 : ec,
60 : NULL);
61 : }
62 0 : return TALER_MHD_REPLY_JSON_PACK (
63 : connection,
64 : MHD_HTTP_NOT_FOUND,
65 : TALER_JSON_pack_ec (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN),
66 : GNUNET_JSON_pack_timestamp ("timestamp",
67 : now),
68 : GNUNET_JSON_pack_data_auto ("exchange_pub",
69 : &epub),
70 : GNUNET_JSON_pack_data_auto ("exchange_sig",
71 : &esig),
72 : GNUNET_JSON_pack_data_auto ("h_denom_pub",
73 : dph));
74 : }
75 :
76 :
77 : MHD_RESULT
78 0 : TEH_RESPONSE_reply_expired_denom_pub_hash (
79 : struct MHD_Connection *connection,
80 : const struct TALER_DenominationHashP *dph,
81 : enum TALER_ErrorCode ec,
82 : const char *oper)
83 : {
84 : struct TALER_ExchangePublicKeyP epub;
85 : struct TALER_ExchangeSignatureP esig;
86 : enum TALER_ErrorCode ecr;
87 : struct GNUNET_TIME_Timestamp now
88 0 : = GNUNET_TIME_timestamp_get ();
89 :
90 0 : GNUNET_assert (NULL != oper);
91 0 : ecr = TALER_exchange_online_denomination_expired_sign (
92 : &TEH_keys_exchange_sign_,
93 : now,
94 : dph,
95 : oper,
96 : &epub,
97 : &esig);
98 0 : if (TALER_EC_NONE != ecr)
99 : {
100 0 : GNUNET_break (0);
101 0 : return TALER_MHD_reply_with_error (connection,
102 : MHD_HTTP_INTERNAL_SERVER_ERROR,
103 : ec,
104 : NULL);
105 : }
106 0 : return TALER_MHD_REPLY_JSON_PACK (
107 : connection,
108 : MHD_HTTP_GONE,
109 : TALER_JSON_pack_ec (ec),
110 : GNUNET_JSON_pack_string ("oper",
111 : oper),
112 : GNUNET_JSON_pack_timestamp ("timestamp",
113 : now),
114 : GNUNET_JSON_pack_data_auto ("exchange_pub",
115 : &epub),
116 : GNUNET_JSON_pack_data_auto ("exchange_sig",
117 : &esig),
118 : GNUNET_JSON_pack_data_auto ("h_denom_pub",
119 : dph));
120 : }
121 :
122 :
123 : MHD_RESULT
124 0 : TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
125 : struct MHD_Connection *connection,
126 : const struct TALER_DenominationHashP *dph)
127 : {
128 : struct TALER_ExchangePublicKeyP epub;
129 : struct TALER_ExchangeSignatureP esig;
130 : struct GNUNET_TIME_Timestamp now;
131 : enum TALER_ErrorCode ec;
132 :
133 0 : now = GNUNET_TIME_timestamp_get ();
134 0 : ec = TALER_exchange_online_denomination_unknown_sign (
135 : &TEH_keys_exchange_sign_,
136 : now,
137 : dph,
138 : &epub,
139 : &esig);
140 0 : if (TALER_EC_NONE != ec)
141 : {
142 0 : GNUNET_break (0);
143 0 : return TALER_MHD_reply_with_error (connection,
144 : MHD_HTTP_INTERNAL_SERVER_ERROR,
145 : ec,
146 : NULL);
147 : }
148 0 : return TALER_MHD_REPLY_JSON_PACK (
149 : connection,
150 : MHD_HTTP_NOT_FOUND,
151 : TALER_JSON_pack_ec (
152 : TALER_EC_EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION),
153 : GNUNET_JSON_pack_timestamp ("timestamp",
154 : now),
155 : GNUNET_JSON_pack_data_auto ("exchange_pub",
156 : &epub),
157 : GNUNET_JSON_pack_data_auto ("exchange_sig",
158 : &esig),
159 : GNUNET_JSON_pack_data_auto ("h_denom_pub",
160 : dph));
161 : }
162 :
163 :
164 : MHD_RESULT
165 23 : TEH_RESPONSE_reply_coin_insufficient_funds (
166 : struct MHD_Connection *connection,
167 : enum TALER_ErrorCode ec,
168 : const struct TALER_DenominationHashP *h_denom_pub,
169 : const struct TALER_CoinSpendPublicKeyP *coin_pub)
170 : {
171 23 : return TALER_MHD_REPLY_JSON_PACK (
172 : connection,
173 : TALER_ErrorCode_get_http_status_safe (ec),
174 : TALER_JSON_pack_ec (ec),
175 : GNUNET_JSON_pack_data_auto ("coin_pub",
176 : coin_pub),
177 : // FIXME - #7267: to be kept only for some of the error types!
178 : GNUNET_JSON_pack_data_auto ("h_denom_pub",
179 : h_denom_pub));
180 : }
181 :
182 :
183 : MHD_RESULT
184 4 : TEH_RESPONSE_reply_coin_conflicting_contract (
185 : struct MHD_Connection *connection,
186 : enum TALER_ErrorCode ec,
187 : const struct TALER_MerchantWireHashP *h_wire)
188 : {
189 4 : return TALER_MHD_REPLY_JSON_PACK (
190 : connection,
191 : TALER_ErrorCode_get_http_status_safe (ec),
192 : GNUNET_JSON_pack_data_auto ("h_wire",
193 : h_wire),
194 : TALER_JSON_pack_ec (ec));
195 : }
196 :
197 :
198 : MHD_RESULT
199 2 : TEH_RESPONSE_reply_coin_denomination_conflict (
200 : struct MHD_Connection *connection,
201 : enum TALER_ErrorCode ec,
202 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
203 : const struct TALER_DenominationPublicKey *prev_denom_pub,
204 : const struct TALER_DenominationSignature *prev_denom_sig)
205 : {
206 2 : return TALER_MHD_REPLY_JSON_PACK (
207 : connection,
208 : TALER_ErrorCode_get_http_status_safe (ec),
209 : TALER_JSON_pack_ec (ec),
210 : GNUNET_JSON_pack_data_auto ("coin_pub",
211 : coin_pub),
212 : TALER_JSON_pack_denom_pub ("prev_denom_pub",
213 : prev_denom_pub),
214 : TALER_JSON_pack_denom_sig ("prev_denom_sig",
215 : prev_denom_sig)
216 : );
217 :
218 : }
219 :
220 :
221 : MHD_RESULT
222 0 : TEH_RESPONSE_reply_coin_age_commitment_conflict (
223 : struct MHD_Connection *connection,
224 : enum TALER_ErrorCode ec,
225 : enum TALER_EXCHANGEDB_CoinKnownStatus status,
226 : const struct TALER_DenominationHashP *h_denom_pub,
227 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
228 : const struct TALER_AgeCommitmentHashP *h_age_commitment)
229 : {
230 : const char *conflict_detail;
231 :
232 0 : switch (status)
233 : {
234 :
235 0 : case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL:
236 0 : conflict_detail = "expected NULL age commitment hash";
237 0 : h_age_commitment = NULL;
238 0 : break;
239 0 : case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL:
240 0 : conflict_detail = "expected non-NULL age commitment hash";
241 0 : break;
242 0 : case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS:
243 0 : conflict_detail = "expected age commitment hash differs";
244 0 : break;
245 0 : default:
246 0 : GNUNET_assert (0);
247 : }
248 :
249 0 : return TALER_MHD_REPLY_JSON_PACK (
250 : connection,
251 : TALER_ErrorCode_get_http_status_safe (ec),
252 : TALER_JSON_pack_ec (ec),
253 : GNUNET_JSON_pack_data_auto ("coin_pub",
254 : coin_pub),
255 : GNUNET_JSON_pack_data_auto ("h_denom_pub",
256 : h_denom_pub),
257 : GNUNET_JSON_pack_allow_null (
258 : GNUNET_JSON_pack_data_auto ("expected_age_commitment_hash",
259 : h_age_commitment)),
260 : GNUNET_JSON_pack_string ("conflict_detail",
261 : conflict_detail)
262 : );
263 : }
264 :
265 :
266 : MHD_RESULT
267 3 : TEH_RESPONSE_reply_reserve_insufficient_balance (
268 : struct MHD_Connection *connection,
269 : enum TALER_ErrorCode ec,
270 : const struct TALER_Amount *reserve_balance,
271 : const struct TALER_Amount *balance_required,
272 : const struct TALER_ReservePublicKeyP *reserve_pub)
273 : {
274 3 : return TALER_MHD_REPLY_JSON_PACK (
275 : connection,
276 : MHD_HTTP_CONFLICT,
277 : TALER_JSON_pack_ec (ec),
278 : TALER_JSON_pack_amount ("balance",
279 : reserve_balance),
280 : TALER_JSON_pack_amount ("requested_amount",
281 : balance_required));
282 : }
283 :
284 :
285 : MHD_RESULT
286 2 : TEH_RESPONSE_reply_reserve_age_restriction_required (
287 : struct MHD_Connection *connection,
288 : uint16_t maximum_allowed_age)
289 : {
290 2 : return TALER_MHD_REPLY_JSON_PACK (
291 : connection,
292 : MHD_HTTP_CONFLICT,
293 : TALER_JSON_pack_ec (TALER_EC_EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED),
294 : GNUNET_JSON_pack_uint64 ("maximum_allowed_age",
295 : maximum_allowed_age));
296 : }
297 :
298 :
299 : MHD_RESULT
300 20 : TEH_RESPONSE_reply_purse_created (
301 : struct MHD_Connection *connection,
302 : struct GNUNET_TIME_Timestamp exchange_timestamp,
303 : const struct TALER_Amount *purse_balance,
304 : const struct TEH_PurseDetails *pd)
305 : {
306 : struct TALER_ExchangePublicKeyP pub;
307 : struct TALER_ExchangeSignatureP sig;
308 : enum TALER_ErrorCode ec;
309 :
310 20 : if (TALER_EC_NONE !=
311 20 : (ec = TALER_exchange_online_purse_created_sign (
312 : &TEH_keys_exchange_sign_,
313 : exchange_timestamp,
314 : pd->purse_expiration,
315 : &pd->target_amount,
316 : purse_balance,
317 : &pd->purse_pub,
318 : &pd->h_contract_terms,
319 : &pub,
320 : &sig)))
321 : {
322 0 : GNUNET_break (0);
323 0 : return TALER_MHD_reply_with_ec (connection,
324 : ec,
325 : NULL);
326 : }
327 20 : return TALER_MHD_REPLY_JSON_PACK (
328 : connection,
329 : MHD_HTTP_OK,
330 : TALER_JSON_pack_amount ("total_deposited",
331 : purse_balance),
332 : GNUNET_JSON_pack_timestamp ("exchange_timestamp",
333 : exchange_timestamp),
334 : GNUNET_JSON_pack_data_auto ("exchange_sig",
335 : &sig),
336 : GNUNET_JSON_pack_data_auto ("exchange_pub",
337 : &pub));
338 : }
339 :
340 :
341 : MHD_RESULT
342 18 : TEH_RESPONSE_reply_kyc_required (
343 : struct MHD_Connection *connection,
344 : const struct TALER_NormalizedPaytoHashP *h_payto,
345 : const struct TALER_EXCHANGEDB_KycStatus *kyc,
346 : bool bad_kyc_auth)
347 : {
348 18 : return TALER_MHD_REPLY_JSON_PACK (
349 : connection,
350 : MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
351 : TALER_JSON_pack_ec (TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED),
352 : GNUNET_JSON_pack_data_auto ("h_payto",
353 : h_payto),
354 : GNUNET_JSON_pack_allow_null (
355 : GNUNET_JSON_pack_data_auto (
356 : "account_pub",
357 : (kyc->have_account_pub
358 : ? &kyc->account_pub
359 : : NULL))),
360 : GNUNET_JSON_pack_allow_null (
361 : bad_kyc_auth
362 : ? GNUNET_JSON_pack_bool ("bad_kyc_auth",
363 : bad_kyc_auth)
364 : : GNUNET_JSON_pack_string ("bad_kyc_auth",
365 : NULL)),
366 : GNUNET_JSON_pack_uint64 ("requirement_row",
367 : kyc->requirement_row));
368 : }
369 :
370 :
371 : MHD_RESULT
372 0 : TEH_RESPONSE_reply_not_modified (
373 : struct MHD_Connection *connection,
374 : const char *etags,
375 : TEH_RESPONSE_SetHeaders cb,
376 : void *cb_cls)
377 : {
378 : MHD_RESULT ret;
379 : struct MHD_Response *resp;
380 :
381 0 : resp = MHD_create_response_from_buffer (0,
382 : NULL,
383 : MHD_RESPMEM_PERSISTENT);
384 0 : if (NULL != cb)
385 0 : cb (cb_cls,
386 : resp);
387 0 : GNUNET_break (MHD_YES ==
388 : MHD_add_response_header (resp,
389 : MHD_HTTP_HEADER_ETAG,
390 : etags));
391 0 : ret = MHD_queue_response (connection,
392 : MHD_HTTP_NOT_MODIFIED,
393 : resp);
394 0 : GNUNET_break (MHD_YES == ret);
395 0 : MHD_destroy_response (resp);
396 0 : return ret;
397 : }
398 :
399 :
400 : /* end of taler-exchange-httpd_responses.c */
|