sync

Backup service to store encrypted wallet databases (experimental)
Log | Files | Refs | Submodules | README | LICENSE

sync_service.h (9126B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2019-2023 Taler Systems SA
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   Anastasis 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 Lesser General Public License for more details.
     12 
     13   You should have received a copy of the GNU Lesser General Public License along with
     14   Anastasis; see the file COPYING.LIB.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file include/sync_service.h
     18  * @brief C interface of libsync, a C library to use sync's HTTP API
     19  * @author Christian Grothoff
     20  */
     21 #ifndef SYNC_SERVICE_H
     22 #define SYNC_SERVICE_H
     23 
     24 #include <gnunet/gnunet_util_lib.h>
     25 #include <taler/taler_error_codes.h>
     26 #include <gnunet/gnunet_curl_lib.h>
     27 #include <jansson.h>
     28 
     29 
     30 GNUNET_NETWORK_STRUCT_BEGIN
     31 
     32 
     33 /**
     34  * Private key identifying an account.
     35  */
     36 struct SYNC_AccountPrivateKeyP
     37 {
     38   /**
     39    * We use EdDSA.
     40    */
     41   struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
     42 };
     43 
     44 
     45 /**
     46  * Public key identifying an account.
     47  */
     48 struct SYNC_AccountPublicKeyP
     49 {
     50   /**
     51    * We use EdDSA.
     52    */
     53   struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub;
     54 };
     55 
     56 
     57 /**
     58  * Data signed by the account public key of a sync client to
     59  * authorize the upload of the backup.
     60  */
     61 struct SYNC_UploadSignaturePS
     62 {
     63   /**
     64    * Set to #TALER_SIGNATURE_SYNC_BACKUP_UPLOAD.
     65    */
     66   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     67 
     68   /**
     69    * Hash of the previous backup, all zeros for none.
     70    */
     71   struct GNUNET_HashCode old_backup_hash GNUNET_PACKED;
     72 
     73   /**
     74    * Hash of the new backup.
     75    */
     76   struct GNUNET_HashCode new_backup_hash GNUNET_PACKED;
     77 
     78 };
     79 
     80 
     81 /**
     82  * Signature made with an account's public key.
     83  */
     84 struct SYNC_AccountSignatureP
     85 {
     86   /**
     87    * We use EdDSA.
     88    */
     89   struct GNUNET_CRYPTO_EddsaSignature eddsa_sig;
     90 };
     91 
     92 GNUNET_NETWORK_STRUCT_END
     93 
     94 
     95 /**
     96  * High-level ways how an upload may conclude.
     97  */
     98 enum SYNC_UploadStatus
     99 {
    100   /**
    101    * Backup was successfully made.
    102    */
    103   SYNC_US_SUCCESS = 0,
    104 
    105   /**
    106    * Account expired or payment was explicitly requested
    107    * by the client.
    108    */
    109   SYNC_US_PAYMENT_REQUIRED = 1,
    110 
    111   /**
    112    * Conflicting backup existed on server. Client should
    113    * reconcile and try again with (using the provided
    114    * recovered backup as the previous backup).
    115    */
    116   SYNC_US_CONFLICTING_BACKUP = 2,
    117 
    118   /**
    119    * HTTP interaction failed, see HTTP status.
    120    */
    121   SYNC_US_HTTP_ERROR = 3,
    122 
    123   /**
    124    * We had an internal error (not sure this can happen,
    125    * but reserved for HTTP 400 status codes).
    126    */
    127   SYNC_US_CLIENT_ERROR = 4,
    128 
    129   /**
    130    * Server had an internal error.
    131    */
    132   SYNC_US_SERVER_ERROR = 5
    133 };
    134 
    135 
    136 /**
    137  * Result of an upload.
    138  */
    139 struct SYNC_UploadDetails
    140 {
    141 
    142   /**
    143    * Taler error code.
    144    */
    145   enum TALER_ErrorCode ec;
    146 
    147   /**
    148    * HTTP status of the request.
    149    */
    150   unsigned int http_status;
    151 
    152   /**
    153    * High level status of the upload operation.
    154    */
    155   enum SYNC_UploadStatus us;
    156 
    157   /**
    158    * Details depending on @e us.
    159    */
    160   union
    161   {
    162 
    163     /**
    164      * Data returned if @e us is #SYNC_US_SUCCESS.
    165      */
    166     struct
    167     {
    168 
    169       /**
    170        * Hash of the synchronized backup.
    171        */
    172       const struct GNUNET_HashCode *curr_backup_hash;
    173 
    174     } success;
    175 
    176     /**
    177      * Previous backup. Returned if @e us is
    178      * #SYNC_US_CONFLICTING_BACKUP
    179      */
    180     struct
    181     {
    182       /**
    183        * Hash over @e existing_backup.
    184        */
    185       struct GNUNET_HashCode existing_backup_hash;
    186 
    187       /**
    188        * Number of bytes in @e existing_backup.
    189        */
    190       size_t existing_backup_size;
    191 
    192       /**
    193        * The backup on the server, which does not match the
    194        * "previous" backup expected by the client and thus
    195        * needs to be decrypted, reconciled and re-uploaded.
    196        */
    197       const void *existing_backup;
    198 
    199     } recovered_backup;
    200 
    201     struct
    202     {
    203       /**
    204        * A taler://pay/-URI with a request to pay the annual fee for
    205        * the service.  Returned if @e us is #SYNC_US_PAYMENT_REQUIRED.
    206        */
    207       const char *payment_request;
    208 
    209     } payment_required;
    210 
    211   } details;
    212 
    213 };
    214 
    215 
    216 /**
    217  * Function called with the results of a #SYNC_upload().
    218  *
    219  * @param cls closure
    220  * @param ud details about the upload operation
    221  */
    222 typedef void
    223 (*SYNC_UploadCallback)(void *cls,
    224                        const struct SYNC_UploadDetails *ud);
    225 
    226 
    227 /**
    228  * Handle for an upload operatoin.
    229  */
    230 struct SYNC_UploadOperation;
    231 
    232 /**
    233  * Options for payment.
    234  */
    235 enum SYNC_PaymentOptions
    236 {
    237   /**
    238    * No special options.
    239    */
    240   SYNC_PO_NONE = 0,
    241 
    242   /**
    243    * Trigger payment even if sync does not require it
    244    * yet (forced payment).
    245    */
    246   SYNC_PO_FORCE_PAYMENT = 1,
    247 
    248   /**
    249    * Request a fresh order to be created, say because the
    250    * existing one was claimed (but not paid) by another wallet.
    251    */
    252   SYNC_PO_FRESH_ORDER = 2
    253 };
    254 
    255 /**
    256  * Upload a @a backup to a Sync server. Note that @a backup must
    257  * have already been compressed, padded and encrypted by the
    258  * client.
    259  *
    260  * While @a pub is theoretically protected by the HTTPS protocol and
    261  * required to access the backup, it should be assumed that an
    262  * adversary might be able to download the backups from the Sync
    263  * server -- or even run the Sync server. Thus, strong encryption
    264  * is essential and NOT implemented by this function.
    265  *
    266  * The use of Anastasis to safely store the Sync encryption keys and
    267  * @a pub is recommended.  Storing @a priv in Anastasis depends on
    268  * your priorities: without @a priv, further updates to the backup are
    269  * not possible, and the user would have to pay for another
    270  * account. OTOH, without @a priv an adversary that compromised
    271  * Anastasis can only read the backups, but not alter or destroy them.
    272  *
    273  * @param ctx for HTTP client request processing
    274  * @param base_url base URL of the Sync server
    275  * @param priv private key of an account with the server
    276  * @param prev_backup_hash hash of the previous backup, NULL for the first upload ever
    277  * @param backup_size number of bytes in @a backup
    278  * @param backup the encrypted backup, must remain in
    279  *         memory until we are done with the operation!
    280  * @param po payment options
    281  * @param paid_order_id ID of the paid order, NULL if no payment was made so far
    282  * @param cb function to call with the result
    283  * @param cb_cls closure for @a cb
    284  * @return handle for the operation
    285  */
    286 struct SYNC_UploadOperation *
    287 SYNC_upload (struct GNUNET_CURL_Context *ctx,
    288              const char *base_url,
    289              struct SYNC_AccountPrivateKeyP *priv,
    290              const struct GNUNET_HashCode *prev_backup_hash,
    291              size_t backup_size,
    292              const void *backup,
    293              enum SYNC_PaymentOptions po,
    294              const char *paid_order_id,
    295              SYNC_UploadCallback cb,
    296              void *cb_cls);
    297 
    298 
    299 /**
    300  * Cancel the upload.  Note that aborting an upload does NOT guarantee
    301  * that it did not complete, it is possible that the server did
    302  * receive the full request before the upload is aborted.
    303  *
    304  * @param[in] uo operation to cancel.
    305  */
    306 void
    307 SYNC_upload_cancel (struct SYNC_UploadOperation *uo);
    308 
    309 
    310 /**
    311  * Detailed results from the successful download.
    312  */
    313 struct SYNC_DownloadDetails
    314 {
    315 
    316   /**
    317    * HTTP status code.
    318    */
    319   unsigned int http_status;
    320 
    321   /**
    322    * Details depending on @e http_status.
    323    */
    324   union
    325   {
    326 
    327     /**
    328      * Details if status is #MHD_HTTP_OK.
    329      */
    330     struct
    331     {
    332 
    333       /**
    334        * Signature (already verified).
    335        */
    336       struct SYNC_AccountSignatureP sig;
    337 
    338       /**
    339        * Hash of the previous version.
    340        */
    341       struct GNUNET_HashCode prev_backup_hash;
    342 
    343       /**
    344        * Hash over @e backup and @e backup_size.
    345        */
    346       struct GNUNET_HashCode curr_backup_hash;
    347 
    348       /**
    349        * The backup we downloaded.
    350        */
    351       const void *backup;
    352 
    353       /**
    354        * Number of bytes in @e backup.
    355        */
    356       size_t backup_size;
    357     } ok;
    358 
    359   } details;
    360 
    361 };
    362 
    363 
    364 /**
    365  * Function called with the results of a #SYNC_download().
    366  *
    367  * @param cls closure
    368  * @param dd download details
    369  */
    370 typedef void
    371 (*SYNC_DownloadCallback)(void *cls,
    372                          const struct SYNC_DownloadDetails *dd);
    373 
    374 
    375 /**
    376  * Handle for a download operation.
    377  */
    378 struct SYNC_DownloadOperation;
    379 
    380 
    381 /**
    382  * Download the latest version of a backup for account @a pub.
    383  *
    384  * @param ctx for HTTP client request processing
    385  * @param base_url base URL of the Sync server
    386  * @param pub account public key
    387  * @param cb function to call with the backup
    388  * @param cb_cls closure for @a cb
    389  * @return handle for the operation
    390  */
    391 struct SYNC_DownloadOperation *
    392 SYNC_download (struct GNUNET_CURL_Context *ctx,
    393                const char *base_url,
    394                const struct SYNC_AccountPublicKeyP *pub,
    395                SYNC_DownloadCallback cb,
    396                void *cb_cls);
    397 
    398 
    399 /**
    400  * Cancel the download.
    401  *
    402  * @param[in] download operation to cancel.
    403  */
    404 void
    405 SYNC_download_cancel (struct SYNC_DownloadOperation *download);
    406 
    407 
    408 #endif  /* SYNC_SERVICE_H */