Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2022 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (at your option) any later version.
9 :
10 : TALER is distributed in the hope that it will be useful, but
11 : WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 : /**
20 : * @file testing/testing_api_cmd_reserve_attest.c
21 : * @brief Implement the /reserve/$RID/attest test command.
22 : * @author Christian Grothoff
23 : */
24 : #include "taler/platform.h"
25 : #include "taler/taler_json_lib.h"
26 : #include <gnunet/gnunet_curl_lib.h>
27 : #include "taler/taler_testing_lib.h"
28 :
29 : /**
30 : * State for a "attest" CMD.
31 : */
32 : struct AttestState
33 : {
34 : /**
35 : * Label to the command which created the reserve to check,
36 : * needed to resort the reserve key.
37 : */
38 : const char *reserve_reference;
39 :
40 : /**
41 : * Handle to the "reserve attest" operation.
42 : */
43 : struct TALER_EXCHANGE_PostReservesAttestHandle *rsh;
44 :
45 : /**
46 : * Private key of the reserve being analyzed.
47 : */
48 : const struct TALER_ReservePrivateKeyP *reserve_priv;
49 :
50 : /**
51 : * Public key of the reserve being analyzed.
52 : */
53 : struct TALER_ReservePublicKeyP reserve_pub;
54 :
55 : /**
56 : * Array of attributes to request, of length @e attrs_len.
57 : */
58 : const char **attrs;
59 :
60 : /**
61 : * Length of the @e attrs array.
62 : */
63 : unsigned int attrs_len;
64 :
65 : /**
66 : * Expected HTTP response code.
67 : */
68 : unsigned int expected_response_code;
69 :
70 : /**
71 : * Interpreter state.
72 : */
73 : struct TALER_TESTING_Interpreter *is;
74 :
75 : /* FIXME: expose fields below as traits... */
76 :
77 : /**
78 : * Attested attributes returned by the exchange.
79 : */
80 : json_t *attributes;
81 :
82 : /**
83 : * Expiration time of the attested attributes.
84 : */
85 : struct GNUNET_TIME_Timestamp expiration_time;
86 :
87 : /**
88 : * Signature by the exchange affirming the attributes.
89 : */
90 : struct TALER_ExchangeSignatureP exchange_sig;
91 :
92 : /**
93 : * Online signing key used by the exchange.
94 : */
95 : struct TALER_ExchangePublicKeyP exchange_pub;
96 : };
97 :
98 :
99 : /**
100 : * Check that the reserve balance and HTTP response code are
101 : * both acceptable.
102 : *
103 : * @param cls closure.
104 : * @param rs HTTP response details
105 : */
106 : static void
107 1 : reserve_attest_cb (
108 : void *cls,
109 : const struct TALER_EXCHANGE_PostReservesAttestResponse *rs)
110 : {
111 1 : struct AttestState *ss = cls;
112 1 : struct TALER_TESTING_Interpreter *is = ss->is;
113 :
114 1 : ss->rsh = NULL;
115 1 : if (ss->expected_response_code != rs->hr.http_status)
116 : {
117 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 : "Unexpected HTTP response code: %d in %s:%u\n",
119 : rs->hr.http_status,
120 : __FILE__,
121 : __LINE__);
122 0 : json_dumpf (rs->hr.reply,
123 : stderr,
124 : JSON_INDENT (2));
125 0 : TALER_TESTING_interpreter_fail (ss->is);
126 0 : return;
127 : }
128 1 : if (MHD_HTTP_OK != rs->hr.http_status)
129 : {
130 0 : TALER_TESTING_interpreter_next (is);
131 0 : return;
132 : }
133 1 : ss->attributes = json_incref ((json_t*) rs->details.ok.attributes);
134 1 : ss->expiration_time = rs->details.ok.expiration_time;
135 1 : ss->exchange_pub = rs->details.ok.exchange_pub;
136 1 : ss->exchange_sig = rs->details.ok.exchange_sig;
137 1 : TALER_TESTING_interpreter_next (is);
138 : }
139 :
140 :
141 : /**
142 : * Run the command.
143 : *
144 : * @param cls closure.
145 : * @param cmd the command being executed.
146 : * @param is the interpreter state.
147 : */
148 : static void
149 1 : attest_run (void *cls,
150 : const struct TALER_TESTING_Command *cmd,
151 : struct TALER_TESTING_Interpreter *is)
152 : {
153 1 : struct AttestState *ss = cls;
154 : const struct TALER_TESTING_Command *create_reserve;
155 : const char *exchange_url;
156 :
157 1 : ss->is = is;
158 1 : exchange_url = TALER_TESTING_get_exchange_url (is);
159 1 : if (NULL == exchange_url)
160 : {
161 0 : GNUNET_break (0);
162 0 : return;
163 : }
164 : create_reserve
165 1 : = TALER_TESTING_interpreter_lookup_command (is,
166 : ss->reserve_reference);
167 :
168 1 : if (NULL == create_reserve)
169 : {
170 0 : GNUNET_break (0);
171 0 : TALER_TESTING_interpreter_fail (is);
172 0 : return;
173 : }
174 1 : if (GNUNET_OK !=
175 1 : TALER_TESTING_get_trait_reserve_priv (create_reserve,
176 : &ss->reserve_priv))
177 : {
178 0 : GNUNET_break (0);
179 0 : TALER_LOG_ERROR ("Failed to find reserve_priv for attest query\n");
180 0 : TALER_TESTING_interpreter_fail (is);
181 0 : return;
182 : }
183 1 : GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
184 : &ss->reserve_pub.eddsa_pub);
185 1 : ss->rsh = TALER_EXCHANGE_post_reserves_attest_create (
186 : TALER_TESTING_interpreter_get_context (is),
187 : exchange_url,
188 : TALER_TESTING_get_keys (is),
189 : ss->reserve_priv,
190 : ss->attrs_len,
191 : ss->attrs);
192 1 : if (NULL == ss->rsh)
193 : {
194 0 : GNUNET_break (0);
195 0 : TALER_TESTING_interpreter_fail (is);
196 0 : return;
197 : }
198 : {
199 : enum TALER_ErrorCode ec;
200 :
201 1 : ec = TALER_EXCHANGE_post_reserves_attest_start (ss->rsh,
202 : &reserve_attest_cb,
203 : ss);
204 1 : if (TALER_EC_NONE != ec)
205 : {
206 0 : GNUNET_break (0);
207 0 : ss->rsh = NULL;
208 0 : TALER_TESTING_interpreter_fail (is);
209 0 : return;
210 : }
211 : }
212 : }
213 :
214 :
215 : /**
216 : * Cleanup the state from a "reserve attest" CMD, and possibly
217 : * cancel a pending operation thereof.
218 : *
219 : * @param cls closure.
220 : * @param cmd the command which is being cleaned up.
221 : */
222 : static void
223 1 : attest_cleanup (void *cls,
224 : const struct TALER_TESTING_Command *cmd)
225 : {
226 1 : struct AttestState *ss = cls;
227 :
228 1 : if (NULL != ss->rsh)
229 : {
230 0 : TALER_TESTING_command_incomplete (ss->is,
231 : cmd->label);
232 0 : TALER_EXCHANGE_post_reserves_attest_cancel (ss->rsh);
233 0 : ss->rsh = NULL;
234 : }
235 1 : json_decref (ss->attributes);
236 1 : GNUNET_free (ss->attrs);
237 1 : GNUNET_free (ss);
238 1 : }
239 :
240 :
241 : struct TALER_TESTING_Command
242 1 : TALER_TESTING_cmd_reserve_attest (const char *label,
243 : const char *reserve_reference,
244 : unsigned int expected_response_code,
245 : ...)
246 : {
247 : struct AttestState *ss;
248 : unsigned int num_args;
249 : const char *ea;
250 : va_list ap;
251 :
252 1 : num_args = 0;
253 1 : va_start (ap, expected_response_code);
254 2 : while (NULL != va_arg (ap, const char *))
255 1 : num_args++;
256 1 : va_end (ap);
257 :
258 1 : GNUNET_assert (NULL != reserve_reference);
259 1 : ss = GNUNET_new (struct AttestState);
260 1 : ss->reserve_reference = reserve_reference;
261 1 : ss->expected_response_code = expected_response_code;
262 1 : ss->attrs_len = num_args;
263 1 : ss->attrs = GNUNET_new_array (num_args,
264 : const char *);
265 1 : num_args = 0;
266 1 : va_start (ap, expected_response_code);
267 2 : while (NULL != (ea = va_arg (ap, const char *)))
268 1 : ss->attrs[num_args++] = ea;
269 1 : va_end (ap);
270 :
271 : {
272 1 : struct TALER_TESTING_Command cmd = {
273 : .cls = ss,
274 : .label = label,
275 : .run = &attest_run,
276 : .cleanup = &attest_cleanup
277 : };
278 :
279 1 : return cmd;
280 : }
281 : }
|