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