challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

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