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