challenger_database_plugin.h (17967B)
1 /* 2 This file is part of Challenger 3 Copyright (C) 2023 Taler Systems SA 4 5 Challenger is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Lesser General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Challenger 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 General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Challenger; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file include/challenger_database_plugin.h 18 * @brief database access for Challenger 19 * @author Christian Grothoff 20 */ 21 #ifndef CHALLENGER_DATABASE_PLUGIN_H 22 #define CHALLENGER_DATABASE_PLUGIN_H 23 24 #include <gnunet/gnunet_util_lib.h> 25 #include <gnunet/gnunet_db_lib.h> 26 #include <jansson.h> 27 #include <taler/taler_util.h> 28 29 30 /** 31 * Nonce used to uniquely (and unpredictably) identify validations. 32 */ 33 struct CHALLENGER_ValidationNonceP 34 { 35 /** 36 * 256-bit nonce used to identify validations. 37 */ 38 uint32_t value[256 / 32]; 39 }; 40 41 42 /** 43 * Nonce to uniquely (and unpredictably) identify access tokens. 44 */ 45 struct CHALLENGER_AccessTokenP 46 { 47 /** 48 * 256-bit nonce used to identify grants. 49 */ 50 uint32_t value[256 / 32]; 51 }; 52 53 54 /** 55 * Handle to interact with the database. 56 * 57 * Functions ending with "_TR" run their OWN transaction scope 58 * and MUST NOT be called from within a transaction setup by the 59 * caller. Functions ending with "_NT" require the caller to 60 * setup a transaction scope. Functions without a suffix are 61 * simple, single SQL queries that MAY be used either way. 62 */ 63 struct CHALLENGER_DatabasePlugin 64 { 65 66 /** 67 * Closure for all callbacks. 68 */ 69 void *cls; 70 71 /** 72 * Name of the library which generated this plugin. Set by the 73 * plugin loader. 74 */ 75 char *library_name; 76 77 /** 78 * Drop challenger tables. Used for testcases. 79 * 80 * @param cls closure 81 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure 82 */ 83 enum GNUNET_GenericReturnValue 84 (*drop_tables)(void *cls); 85 86 87 /** 88 * Create the necessary tables if they are not present 89 * 90 * @param cls the @e cls of this struct with the plugin-specific state 91 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure 92 */ 93 enum GNUNET_GenericReturnValue 94 (*create_tables)(void *cls); 95 96 97 /** 98 * Do a pre-flight check that we are not in an uncommitted transaction. 99 * If we are, try to commit the previous transaction and output a warning. 100 * Does not return anything, as we will continue regardless of the outcome. 101 * 102 * @param cls the `struct PostgresClosure` with the plugin-specific state 103 * @return #GNUNET_OK if everything is fine 104 * #GNUNET_NO if a transaction was rolled back 105 * #GNUNET_SYSERR on hard errors 106 */ 107 enum GNUNET_GenericReturnValue 108 (*preflight)(void *cls); 109 110 111 /** 112 * Start a transaction. 113 * 114 * @param cls the `struct PostgresClosure` with the plugin-specific state 115 * @param name unique name identifying the transaction (for debugging), 116 * must point to a constant 117 * @return #GNUNET_OK on success 118 */ 119 enum GNUNET_GenericReturnValue 120 (*begin_transaction)(void *cls, 121 const char *name); 122 123 124 /** 125 * Commit the current transaction of a database connection. 126 * 127 * @param cls the `struct PostgresClosure` with the plugin-specific state 128 * @return transaction status code 129 */ 130 enum GNUNET_DB_QueryStatus 131 (*commit_transaction)(void *cls); 132 133 134 /** 135 * Roll back the current transaction of a database connection. 136 * 137 * @param cls the `struct PostgresClosure` with the plugin-specific state 138 */ 139 void 140 (*rollback) (void *cls); 141 142 /** 143 * Function called to perform "garbage collection" on the 144 * database, expiring records we no longer require. 145 * 146 * @param cls closure 147 * @param expire expiration time to use 148 * @return transaction status 149 */ 150 enum GNUNET_DB_QueryStatus 151 (*gc)(void *cls, 152 struct GNUNET_TIME_Absolute expire); 153 154 155 /** 156 * Add client to the list of authorized clients. 157 * 158 * @param cls 159 * @param client_url URL of the client 160 * @param client_secret authorization secret for the client 161 * @param[out] client_id set to the client ID on success 162 * @return transaction status 163 */ 164 enum GNUNET_DB_QueryStatus 165 (*client_add)(void *cls, 166 const char *client_url, 167 const char *client_secret, 168 uint64_t *client_id); 169 170 171 /** 172 * Modify client in the list of authorized clients. 173 * 174 * @param cls 175 * @param client_id the client ID on success 176 * @param client_url URL of the client 177 * @param client_secret authorization secret for the client, NULL to not modify the secret 178 * @return transaction status 179 */ 180 enum GNUNET_DB_QueryStatus 181 (*client_modify)(void *cls, 182 uint64_t client_id, 183 const char *client_url, 184 const char *client_secret); 185 186 /** 187 * Delete client from the list of authorized clients. 188 * 189 * @param cls 190 * @param client_url URL of the client 191 * @return transaction status 192 */ 193 enum GNUNET_DB_QueryStatus 194 (*client_delete)(void *cls, 195 const char *client_url); 196 197 198 /** 199 * Check if a client is in the list of authorized clients. If @a 200 * counter_increment is non-zero, the validation counter of the 201 * client is incremented by the given value if the client was found. 202 * 203 * @param cls 204 * @param client_id ID of the client 205 * @param client_secret secret of the client 206 * @param counter_increment change in validation counter 207 * @param[out] client_url set client redirect URL (if known) 208 * @return transaction status 209 */ 210 enum GNUNET_DB_QueryStatus 211 (*client_check)(void *cls, 212 uint64_t client_id, 213 const char *client_secret, 214 uint32_t counter_increment, 215 char **client_url); 216 217 218 /** 219 * Check if a client is in the list of authorized clients. 220 * 221 * @param cls 222 * @param client_url client redirect URL (if known) 223 * @param client_secret secret of the client 224 * @param[out] set to client_id ID of the client if found 225 * @return transaction status 226 */ 227 enum GNUNET_DB_QueryStatus 228 (*client_check2)(void *cls, 229 const char *client_url, 230 const char *client_secret, 231 uint64_t *client_id); 232 233 234 /** 235 * Start validation process by setting up a validation entry. Allows 236 * the respective user who learns the @a nonce to later begin the 237 * process. 238 * 239 * @param cls closure 240 * @param client_id ID of the client 241 * @param nonce unique nonce to use to identify the validation 242 * @param expiration_time when will the validation expire 243 * @param initial_address address the user should validate, 244 * NULL if the user should enter it themselves 245 * @return transaction status 246 */ 247 enum GNUNET_DB_QueryStatus 248 (*setup_nonce)(void *cls, 249 uint64_t client_id, 250 const struct CHALLENGER_ValidationNonceP *nonce, 251 struct GNUNET_TIME_Absolute expiration_time, 252 const json_t *initial_address); 253 254 255 /** 256 * Set the user-provided address and PKCE parameters in a validation process. 257 * Updates the address and decrements the "addresses left" counter. If the 258 * address did not change, the operation is successful even without 259 * the counter change. 260 * 261 * @param cls 262 * @param nonce unique nonce to use to identify the validation 263 * @param client_id client that initiated the validation 264 * @param client_scope scope of the validation 265 * @param client_state state of the client 266 * @param client_redirect_uri where to redirect at the end, NULL to use a unique one registered for the client 267 * @param code_challenge PKCE code challenge 268 * @param code_challenge_method PKCE code challenge method 269 * @param[out] last_address set to the last address used 270 * @param[out] address_attempts_left set to number of address changing attempts left for this address 271 * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested 272 * @param[out] auth_attempts_left set to number of authentication attempts remaining 273 * @param[out] solved set to true if the challenge is already solved 274 * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a last_address; 0 if never sent 275 * @return transaction status: 276 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the address was changed 277 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not permit further changes to the address (attempts exhausted) 278 * #GNUNET_DB_STATUS_HARD_ERROR on failure 279 */ 280 enum GNUNET_DB_QueryStatus 281 (*authorize_start)(void *cls, 282 const struct CHALLENGER_ValidationNonceP *nonce, 283 uint64_t client_id, 284 const char *client_scope, 285 const char *client_state, 286 const char *client_redirect_uri, 287 const char *code_challenge, 288 uint32_t code_challenge_method, 289 json_t **last_address, 290 uint32_t *address_attempts_left, 291 uint32_t *pin_transmissions_left, 292 uint32_t *auth_attempts_left, 293 bool *solved, 294 struct GNUNET_TIME_Absolute *last_tx_time); 295 296 /** 297 * Set the user-provided address in a validation process. Updates 298 * the address and decrements the "addresses left" counter. If the 299 * address did not change, the operation is successful even without 300 * the counter change. 301 * 302 * @param cls closure 303 * @param nonce unique nonce to use to identify the validation 304 * @param address the new address to validate 305 * @param validation_duration minimum time between transmissions 306 * @param[in,out] tan set to the PIN/TAN last send to @a address, input should be random PIN/TAN to use if address did not change 307 * @param[out] state set to client's OAuth2 state if available 308 * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a address, input should be current time to use if the existing value for tx_time is past @a next_tx_time 309 * @param[out] pin_transmit set to true if we should transmit the @a last_pin to the @a address 310 * @param[out] auth_attempts_left set to number of attempts the user has left on this pin 311 * @param[out] client_redirect_uri redirection URI of the client (for reporting failures) 312 * @param[out] address_refused set to true if the address was refused (address change attempts exhausted) 313 * @param[out] solved set to true if the challenge is already solved 314 * @return transaction status: 315 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the address was changed 316 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not permit further changes to the address (attempts exhausted) 317 * #GNUNET_DB_STATUS_HARD_ERROR on failure 318 */ 319 enum GNUNET_DB_QueryStatus 320 (*challenge_set_address_and_pin)( 321 void *cls, 322 const struct CHALLENGER_ValidationNonceP *nonce, 323 const json_t *address, 324 struct GNUNET_TIME_Relative validation_duration, 325 uint32_t *tan, 326 char **state, 327 struct GNUNET_TIME_Absolute *last_tx_time, 328 uint32_t *auth_attempts_left, 329 bool *pin_transmit, 330 char **client_redirect_uri, 331 bool *address_refused, 332 bool *solved); 333 334 335 /** 336 * Check PIN entered to validate an address. 337 * 338 * @param cls 339 * @param nonce unique nonce to use to identify the validation 340 * @param new_pin the PIN the user entered 341 * @param[out] solved set to true if the PIN was correct 342 * @param[out] exhausted set to true if the number of attempts to enter the correct PIN has been exhausted 343 * @param[out] no_challenge set to true if we never even issued a challenge 344 * @param[out] state set to client's OAuth2 state if available 345 * @param[out] addr_left set to number of address changes remaining 346 * @param[out] auth_attempts_left set to number of authentication attempts remaining 347 * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested 348 * @param[out] client_redirect_uri set to OAuth2 client redirect URI 349 * @return transaction status: 350 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found 351 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce 352 * #GNUNET_DB_STATUS_HARD_ERROR on failure 353 */ 354 enum GNUNET_DB_QueryStatus 355 (*validate_solve_pin)(void *cls, 356 const struct CHALLENGER_ValidationNonceP *nonce, 357 uint32_t new_pin, 358 bool *solved, 359 bool *exhausted, 360 bool *no_challenge, 361 char **state, 362 uint32_t *addr_left, 363 uint32_t *auth_attempts_left, 364 uint32_t *pin_transmissions_left, 365 char **client_redirect_uri); 366 367 368 /** 369 * Return validation details. Used by ``/solve``, ``/auth`` and 370 * ``/info`` endpoints to authorize and return validated user 371 * address to the client. 372 * 373 * @param cls 374 * @param nonce unique nonce to use to identify the validation 375 * @param[out] client_secret set to secret of client (for client that setup the challenge) 376 * @param[out] address set to client-provided address 377 * @param[out] client_scope set to OAuth2 scope 378 * @param[out] client_state set to client state 379 * @param[out] client_redirect_uri set to client redirect URL 380 * @return transaction status: 381 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found 382 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce 383 * #GNUNET_DB_STATUS_HARD_ERROR on failure 384 */ 385 enum GNUNET_DB_QueryStatus 386 (*validation_get)(void *cls, 387 const struct CHALLENGER_ValidationNonceP *nonce, 388 char **client_secret, 389 json_t **address, 390 char **client_scope, 391 char **client_state, 392 char **client_redirect_uri); 393 394 395 /** 396 * Return address known for a particular nonce. 397 * 398 * @param cls 399 * @param nonce unique nonce to use to identify the validation 400 * @param[out] address set to client-provided address, can be set to NULL! 401 * @return transaction status: 402 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found 403 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce 404 * #GNUNET_DB_STATUS_HARD_ERROR on failure 405 */ 406 enum GNUNET_DB_QueryStatus 407 (*address_get)(void *cls, 408 const struct CHALLENGER_ValidationNonceP *nonce, 409 json_t **address); 410 411 412 /** 413 * Return validation details including PKCE parameters. Used by `/solve`, `/auth`, and 414 * `/info` endpoints to authorize and return validated user address to the client. 415 * 416 * @param cls 417 * @param nonce unique nonce to use to identify the validation 418 * @param[out] client_secret set to secret of client (for client that setup the challenge) 419 * @param[out] address set to client-provided address 420 * @param[out] client_scope set to OAuth2 scope 421 * @param[out] client_state set to client state 422 * @param[out] client_redirect_uri set to client redirect URL 423 * @param[out] code_challenge set to PKCE code challenge 424 * @param[out] code_challenge_method set to PKCE code challenge method 425 * @return transaction status: 426 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found 427 * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce 428 * #GNUNET_DB_STATUS_HARD_ERROR on failure 429 */ 430 enum GNUNET_DB_QueryStatus 431 (*validation_get_pkce)(void *cls, 432 const struct CHALLENGER_ValidationNonceP *nonce, 433 char **client_secret, 434 json_t **address, 435 char **client_scope, 436 char **client_state, 437 char **client_redirect_uri, 438 char **code_challenge, 439 uint32_t *code_challenge_method); 440 441 /** 442 * Add access @a grant to address under @a nonce. 443 * 444 * @param cls closure 445 * @param nonce validation process to grant access to 446 * @param grant grant token that grants access 447 * @param grant_expiration for how long should the grant be valid 448 * @param address_expiration for how long after validation do we consider addresses to be valid 449 * @return transaction status 450 */ 451 enum GNUNET_DB_QueryStatus 452 (*token_add_token)(void *cls, 453 const struct CHALLENGER_ValidationNonceP *nonce, 454 const struct CHALLENGER_AccessTokenP *grant, 455 struct GNUNET_TIME_Relative grant_expiration, 456 struct GNUNET_TIME_Relative address_expiration); 457 458 459 /** 460 * Return @a address which @a grant gives access to. 461 * 462 * @param cls closure 463 * @param grant grant token that grants access 464 * @param[out] rowid account identifier within challenger 465 * @param[out] address set to the address under @a grant 466 * @param[out] address_expiration set to how long we consider @a address to be valid 467 * @return transaction status 468 */ 469 enum GNUNET_DB_QueryStatus 470 (*info_get_token)(void *cls, 471 const struct CHALLENGER_AccessTokenP *grant, 472 uint64_t *rowid, 473 json_t **address, 474 struct GNUNET_TIME_Timestamp *address_expiration); 475 476 477 }; 478 #endif