testing_api_cmd_revoke_sign_key.c (11253B)
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 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_revoke_sign_key.c 21 * @brief Implement the revoke test command. 22 * @author Christian Grothoff 23 */ 24 #include "taler/taler_json_lib.h" 25 #include <gnunet/gnunet_curl_lib.h> 26 struct RevokeState; 27 #define TALER_EXCHANGE_POST_MANAGEMENT_SIGNKEYS_REVOKE_RESULT_CLOSURE \ 28 struct RevokeState 29 #include "taler/exchange/post-management-signkeys-EXCHANGE_PUB-revoke.h" 30 #include "taler/taler_testing_lib.h" 31 32 33 /** 34 * State for a "revoke" CMD. 35 */ 36 struct RevokeState 37 { 38 /** 39 * Expected HTTP status code. 40 */ 41 unsigned int expected_response_code; 42 43 /** 44 * Command that offers a signination to revoke. 45 */ 46 const char *coin_reference; 47 48 /** 49 * The interpreter state. 50 */ 51 struct TALER_TESTING_Interpreter *is; 52 53 /** 54 * Handle for the operation. 55 */ 56 struct TALER_EXCHANGE_PostManagementSignkeysRevokeHandle *kh; 57 58 /** 59 * Should we use a bogus signature? 60 */ 61 bool bad_sig; 62 63 }; 64 65 66 /** 67 * Function called with information about the post revocation operation result. 68 * 69 * @param rs closure with a `struct RevokeState *` 70 * @param rsr response data 71 */ 72 static void 73 success_cb ( 74 struct RevokeState *rs, 75 const struct TALER_EXCHANGE_PostManagementSignkeysRevokeResponse *rsr) 76 { 77 const struct TALER_EXCHANGE_HttpResponse *hr = &rsr->hr; 78 79 rs->kh = NULL; 80 if (rs->expected_response_code != hr->http_status) 81 { 82 TALER_TESTING_unexpected_status (rs->is, 83 hr->http_status, 84 rs->expected_response_code); 85 return; 86 } 87 TALER_TESTING_interpreter_next (rs->is); 88 } 89 90 91 /** 92 * Cleanup the state. 93 * 94 * @param cls closure, must be a `struct RevokeState`. 95 * @param cmd the command which is being cleaned up. 96 */ 97 static void 98 revoke_cleanup (void *cls, 99 const struct TALER_TESTING_Command *cmd) 100 { 101 struct RevokeState *rs = cls; 102 103 if (NULL != rs->kh) 104 { 105 TALER_EXCHANGE_post_management_signkeys_revoke_cancel (rs->kh); 106 rs->kh = NULL; 107 } 108 GNUNET_free (rs); 109 } 110 111 112 /** 113 * Offer internal data from a "revoke" CMD to other CMDs. 114 * 115 * @param cls closure 116 * @param[out] ret result (could be anything) 117 * @param trait name of the trait 118 * @param index index number of the object to offer. 119 * @return #GNUNET_OK on success 120 */ 121 static int 122 revoke_traits (void *cls, 123 const void **ret, 124 const char *trait, 125 unsigned int index) 126 { 127 struct RevokeState *rs = cls; 128 struct TALER_TESTING_Trait traits[] = { 129 TALER_TESTING_trait_end () 130 }; 131 132 (void) rs; 133 return TALER_TESTING_get_trait (traits, 134 ret, 135 trait, 136 index); 137 } 138 139 140 /** 141 * Run the "revoke" command for a signing key. 142 * 143 * @param cls closure. 144 * @param cmd the command to execute. 145 * @param is the interpreter state. 146 */ 147 static void 148 revoke_run (void *cls, 149 const struct TALER_TESTING_Command *cmd, 150 struct TALER_TESTING_Interpreter *is) 151 { 152 struct RevokeState *rs = cls; 153 const struct TALER_TESTING_Command *coin_cmd; 154 const struct TALER_ExchangePublicKeyP *exchange_pub; 155 struct TALER_MasterSignatureP master_sig; 156 const char *exchange_url; 157 158 { 159 const struct TALER_TESTING_Command *exchange_cmd; 160 161 exchange_cmd = TALER_TESTING_interpreter_get_command (is, 162 "exchange"); 163 if (NULL == exchange_cmd) 164 { 165 GNUNET_break (0); 166 TALER_TESTING_interpreter_fail (is); 167 return; 168 } 169 GNUNET_assert (GNUNET_OK == 170 TALER_TESTING_get_trait_exchange_url (exchange_cmd, 171 &exchange_url)); 172 } 173 rs->is = is; 174 /* Get sign pub from trait */ 175 coin_cmd = TALER_TESTING_interpreter_lookup_command (is, 176 rs->coin_reference); 177 178 if (NULL == coin_cmd) 179 { 180 GNUNET_break (0); 181 TALER_TESTING_interpreter_fail (is); 182 return; 183 } 184 GNUNET_assert (GNUNET_OK == 185 TALER_TESTING_get_trait_exchange_pub (coin_cmd, 186 0, 187 &exchange_pub)); 188 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 189 "Trying to revoke sign '%s..'\n", 190 TALER_B2S (exchange_pub)); 191 if (rs->bad_sig) 192 { 193 memset (&master_sig, 194 42, 195 sizeof (master_sig)); 196 } 197 else 198 { 199 const struct TALER_TESTING_Command *exchange_cmd; 200 const struct TALER_MasterPrivateKeyP *master_priv; 201 202 exchange_cmd = TALER_TESTING_interpreter_get_command (is, 203 "exchange"); 204 if (NULL == exchange_cmd) 205 { 206 GNUNET_break (0); 207 TALER_TESTING_interpreter_fail (is); 208 return; 209 } 210 GNUNET_assert (GNUNET_OK == 211 TALER_TESTING_get_trait_master_priv (exchange_cmd, 212 &master_priv)); 213 TALER_exchange_offline_signkey_revoke_sign (exchange_pub, 214 master_priv, 215 &master_sig); 216 } 217 rs->kh = TALER_EXCHANGE_post_management_signkeys_revoke_create ( 218 TALER_TESTING_interpreter_get_context (is), 219 exchange_url, 220 exchange_pub, 221 &master_sig); 222 if (NULL == rs->kh) 223 { 224 GNUNET_break (0); 225 TALER_TESTING_interpreter_fail (is); 226 return; 227 } 228 TALER_EXCHANGE_post_management_signkeys_revoke_start (rs->kh, &success_cb, rs) 229 ; 230 } 231 232 233 struct TALER_TESTING_Command 234 TALER_TESTING_cmd_revoke_sign_key ( 235 const char *label, 236 unsigned int expected_response_code, 237 bool bad_sig, 238 const char *sign_ref) 239 { 240 struct RevokeState *rs; 241 242 rs = GNUNET_new (struct RevokeState); 243 rs->expected_response_code = expected_response_code; 244 rs->coin_reference = sign_ref; 245 rs->bad_sig = bad_sig; 246 { 247 struct TALER_TESTING_Command cmd = { 248 .cls = rs, 249 .label = label, 250 .run = &revoke_run, 251 .cleanup = &revoke_cleanup, 252 .traits = &revoke_traits 253 }; 254 255 return cmd; 256 } 257 } 258 259 260 /** 261 * State for a "check signkey revoked" CMD. 262 */ 263 struct CheckRevokedState 264 { 265 /** 266 * Command that offers the revoked signing key. 267 */ 268 const char *signkey_ref; 269 270 /** 271 * "get exchange" command that downloaded /keys before the revocation. 272 */ 273 const char *keys_before_ref; 274 275 /** 276 * "get exchange" command that downloaded /keys after the revocation. 277 */ 278 const char *keys_after_ref; 279 }; 280 281 282 /** 283 * Obtain the /keys of the "get exchange" command @a label. 284 * 285 * @param is interpreter state 286 * @param label label of the command 287 * @return NULL on error 288 */ 289 static const struct TALER_EXCHANGE_Keys * 290 get_keys_of (struct TALER_TESTING_Interpreter *is, 291 const char *label) 292 { 293 const struct TALER_TESTING_Command *cmd; 294 struct TALER_EXCHANGE_Keys *keys; 295 296 cmd = TALER_TESTING_interpreter_lookup_command (is, 297 label); 298 if ( (NULL == cmd) || 299 (GNUNET_OK != 300 TALER_TESTING_get_trait_keys (cmd, 301 &keys)) ) 302 return NULL; 303 return keys; 304 } 305 306 307 /** 308 * Run the "check signkey revoked" command. 309 * 310 * @param cls a `struct CheckRevokedState` 311 * @param cmd the command currently being executed. 312 * @param is the interpreter state. 313 */ 314 static void 315 check_revoked_run (void *cls, 316 const struct TALER_TESTING_Command *cmd, 317 struct TALER_TESTING_Interpreter *is) 318 { 319 struct CheckRevokedState *crs = cls; 320 const struct TALER_TESTING_Command *sk_cmd; 321 const struct TALER_ExchangePublicKeyP *exchange_pub; 322 const struct TALER_EXCHANGE_Keys *before; 323 const struct TALER_EXCHANGE_Keys *after; 324 325 (void) cmd; 326 sk_cmd = TALER_TESTING_interpreter_lookup_command (is, 327 crs->signkey_ref); 328 before = get_keys_of (is, 329 crs->keys_before_ref); 330 after = get_keys_of (is, 331 crs->keys_after_ref); 332 if ( (NULL == sk_cmd) || 333 (GNUNET_OK != 334 TALER_TESTING_get_trait_exchange_pub (sk_cmd, 335 0, 336 &exchange_pub)) || 337 (NULL == before) || 338 (NULL == after) ) 339 { 340 GNUNET_break (0); 341 TALER_TESTING_interpreter_fail (is); 342 return; 343 } 344 /* The key was valid before the revocation ... */ 345 if (GNUNET_OK != 346 TALER_EXCHANGE_test_signing_key (before, 347 exchange_pub)) 348 { 349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 350 "Signing key %s was not valid before its revocation\n", 351 TALER_B2S (exchange_pub)); 352 TALER_TESTING_interpreter_fail (is); 353 return; 354 } 355 /* ... /keys no longer lists it after the revocation ... */ 356 for (unsigned int i = 0; i<after->num_sign_keys; i++) 357 { 358 if (0 == 359 GNUNET_memcmp (exchange_pub, 360 &after->sign_keys[i].key)) 361 { 362 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 363 "/keys still lists revoked signing key %s\n", 364 TALER_B2S (exchange_pub)); 365 TALER_TESTING_interpreter_fail (is); 366 return; 367 } 368 } 369 /* ... so the client rejects replies signed with it. */ 370 if (GNUNET_SYSERR != 371 TALER_EXCHANGE_test_signing_key (after, 372 exchange_pub)) 373 { 374 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 375 "Client still accepts revoked signing key %s\n", 376 TALER_B2S (exchange_pub)); 377 TALER_TESTING_interpreter_fail (is); 378 return; 379 } 380 TALER_TESTING_interpreter_next (is); 381 } 382 383 384 /** 385 * Free the state of a "check signkey revoked" CMD. 386 * 387 * @param cls a `struct CheckRevokedState` 388 * @param cmd the command which is being cleaned up. 389 */ 390 static void 391 check_revoked_cleanup (void *cls, 392 const struct TALER_TESTING_Command *cmd) 393 { 394 struct CheckRevokedState *crs = cls; 395 396 (void) cmd; 397 GNUNET_free (crs); 398 } 399 400 401 struct TALER_TESTING_Command 402 TALER_TESTING_cmd_check_signkey_revoked ( 403 const char *label, 404 const char *signkey_ref, 405 const char *keys_before_ref, 406 const char *keys_after_ref) 407 { 408 struct CheckRevokedState *crs; 409 410 crs = GNUNET_new (struct CheckRevokedState); 411 crs->signkey_ref = signkey_ref; 412 crs->keys_before_ref = keys_before_ref; 413 crs->keys_after_ref = keys_after_ref; 414 { 415 struct TALER_TESTING_Command cmd = { 416 .cls = crs, 417 .label = label, 418 .run = &check_revoked_run, 419 .cleanup = &check_revoked_cleanup 420 }; 421 422 return cmd; 423 } 424 }