gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] 06/07: intermediate patch towards implemen


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] 06/07: intermediate patch towards implementing #5136
Date: Sat, 13 Oct 2018 19:46:04 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit 504017bc6584d7c8fe90e6c0f861f4566739a736
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Oct 13 19:14:11 2018 +0200

    intermediate patch towards implementing #5136
---
 src/exchange-lib/exchange_api_handle.c       | 519 +++++++++++++++++++--------
 src/exchange/taler-exchange-httpd_keystate.c |  87 +++--
 src/include/taler_exchange_service.h         |   7 +-
 3 files changed, 429 insertions(+), 184 deletions(-)

diff --git a/src/exchange-lib/exchange_api_handle.c 
b/src/exchange-lib/exchange_api_handle.c
index 3891ee9c..c9795f30 100644
--- a/src/exchange-lib/exchange_api_handle.c
+++ b/src/exchange-lib/exchange_api_handle.c
@@ -41,6 +41,12 @@
  */
 #define TALER_PROTOCOL_AGE 0
 
+/**
+ * Current version for (local) JSON serialization of persisted 
+ * /keys data.
+ */ 
+#define TALER_SERIALIZATION_FORMAT_VERSION 0
+
 
 /**
  * Log error related to CURL operations.
@@ -205,6 +211,7 @@ free_keys_request (struct KeysRequest *kr)
  * Parse a exchange's signing key encoded in JSON.
  *
  * @param[out] sign_key where to return the result
+ * @param check_sigs should we check signatures?
  * @param[in] sign_key_obj json to parse
  * @param master_key master key to use to verify signature
  * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
@@ -212,58 +219,57 @@ free_keys_request (struct KeysRequest *kr)
  */
 static int
 parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
+                   int check_sigs,
                     json_t *sign_key_obj,
                     const struct TALER_MasterPublicKeyP *master_key)
 {
   struct TALER_ExchangeSigningKeyValidityPS sign_key_issue;
   struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct GNUNET_TIME_Absolute valid_from;
-  struct GNUNET_TIME_Absolute valid_until;
-  struct GNUNET_TIME_Absolute valid_legal;
   struct GNUNET_JSON_Specification spec[] = {
+    /* must be first, we skip this one if "check_sigs" is 0! */
     GNUNET_JSON_spec_fixed_auto ("master_sig",
                                  &sig),
     GNUNET_JSON_spec_fixed_auto ("key",
-                                 &sign_key_issue.signkey_pub),
+                                 &sign_key->key),
     GNUNET_JSON_spec_absolute_time ("stamp_start",
-                                    &valid_from),
+                                    &sign_key->valid_from),
     GNUNET_JSON_spec_absolute_time ("stamp_expire",
-                                    &valid_until),
+                                    &sign_key->valid_until),
     GNUNET_JSON_spec_absolute_time ("stamp_end",
-                                    &valid_legal),
+                                    &sign_key->valid_legal),
     GNUNET_JSON_spec_end()
   };
 
   if (GNUNET_OK !=
       GNUNET_JSON_parse (sign_key_obj,
-                         spec,
+                         check_sigs ? spec : &spec[1],
                          NULL, NULL))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
 
+  if (! check_sigs)
+    return GNUNET_OK;
+  sign_key_issue.signkey_pub = sign_key->key;
   sign_key_issue.purpose.purpose = htonl 
(TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
   sign_key_issue.purpose.size =
     htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS)
-           - offsetof (struct TALER_ExchangeSigningKeyValidityPS,
-                       purpose));
+          - offsetof (struct TALER_ExchangeSigningKeyValidityPS,
+                      purpose));
   sign_key_issue.master_public_key = *master_key;
-  sign_key_issue.start = GNUNET_TIME_absolute_hton (valid_from);
-  sign_key_issue.expire = GNUNET_TIME_absolute_hton (valid_until);
-  sign_key_issue.end = GNUNET_TIME_absolute_hton (valid_legal);
+  sign_key_issue.start = GNUNET_TIME_absolute_hton (sign_key->valid_from);
+  sign_key_issue.expire = GNUNET_TIME_absolute_hton (sign_key->valid_until);
+  sign_key_issue.end = GNUNET_TIME_absolute_hton (sign_key->valid_legal);
   if (GNUNET_OK !=
       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
-                                  &sign_key_issue.purpose,
-                                  &sig,
-                                  &master_key->eddsa_pub))
+                                 &sign_key_issue.purpose,
+                                 &sig,
+                                 &master_key->eddsa_pub))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  sign_key->valid_from = valid_from;
-  sign_key->valid_until = valid_until;
-  sign_key->key = sign_key_issue.signkey_pub;
   return GNUNET_OK;
 }
 
@@ -272,6 +278,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey 
*sign_key,
  * Parse a exchange's denomination key encoded in JSON.
  *
  * @param[out] denom_key where to return the result
+ * @param check_sigs should we check signatures?
  * @param[in] denom_key_obj json to parse
  * @param master_key master key to use to verify signature
  * @param hash_context where to accumulate data for signature verification
@@ -280,99 +287,85 @@ parse_json_signkey (struct 
TALER_EXCHANGE_SigningPublicKey *sign_key,
  */
 static int
 parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
+                    int check_sigs,
                      json_t *denom_key_obj,
                      struct TALER_MasterPublicKeyP *master_key,
                      struct GNUNET_HashContext *hash_context)
 {
-  struct GNUNET_TIME_Absolute valid_from;
-  struct GNUNET_TIME_Absolute withdraw_valid_until;
-  struct GNUNET_TIME_Absolute expire_deposit;
-  struct GNUNET_TIME_Absolute expire_legal;
-  struct TALER_Amount value;
-  struct TALER_Amount fee_withdraw;
-  struct TALER_Amount fee_deposit;
-  struct TALER_Amount fee_refresh;
-  struct TALER_Amount fee_refund;
   struct TALER_DenominationKeyValidityPS denom_key_issue;
-  struct GNUNET_CRYPTO_RsaPublicKey *pk;
   struct GNUNET_CRYPTO_EddsaSignature sig;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("master_sig",
                                 &sig),
+    /* master_sig must be first as when 'check_sigs' is set, we
+       start at &spec[1]! */
     GNUNET_JSON_spec_absolute_time ("stamp_expire_deposit",
-                                   &expire_deposit),
+                                   &denom_key->expire_deposit),
     GNUNET_JSON_spec_absolute_time ("stamp_expire_withdraw",
-                                   &withdraw_valid_until),
+                                   &denom_key->withdraw_valid_until),
     GNUNET_JSON_spec_absolute_time ("stamp_start",
-                                   &valid_from),
+                                   &denom_key->valid_from),
     GNUNET_JSON_spec_absolute_time ("stamp_expire_legal",
-                                   &expire_legal),
+                                   &denom_key->expire_legal),
     TALER_JSON_spec_amount ("value",
-                           &value),
+                           &denom_key->value),
     TALER_JSON_spec_amount ("fee_withdraw",
-                           &fee_withdraw),
+                           &denom_key->fee_withdraw),
     TALER_JSON_spec_amount ("fee_deposit",
-                           &fee_deposit),
+                           &denom_key->fee_deposit),
     TALER_JSON_spec_amount ("fee_refresh",
-                           &fee_refresh),
+                           &denom_key->fee_refresh),
     TALER_JSON_spec_amount ("fee_refund",
-                           &fee_refund),
+                           &denom_key->fee_refund),
     GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                             &pk),
+                                    &denom_key->key.rsa_public_key),
     GNUNET_JSON_spec_end()
   };
 
   if (GNUNET_OK !=
       GNUNET_JSON_parse (denom_key_obj,
-                         spec, NULL, NULL))
+                         (check_sigs) ? spec : &spec[1],
+                        NULL, NULL))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
 
+  GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
+                                     &denom_key->h_key);
+  if (! check_sigs)
+    return GNUNET_OK;
   memset (&denom_key_issue,
-          0,
-          sizeof (denom_key_issue));
-  GNUNET_CRYPTO_rsa_public_key_hash (pk,
-                                     &denom_key_issue.denom_hash);
+         0,
+         sizeof (denom_key_issue));
   denom_key_issue.purpose.purpose
     = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
   denom_key_issue.purpose.size
     = htonl (sizeof (struct TALER_DenominationKeyValidityPS));
   denom_key_issue.master = *master_key;
-  denom_key_issue.start = GNUNET_TIME_absolute_hton (valid_from);
-  denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton 
(withdraw_valid_until);
-  denom_key_issue.expire_deposit = GNUNET_TIME_absolute_hton (expire_deposit);
-  denom_key_issue.expire_legal = GNUNET_TIME_absolute_hton (expire_legal);
+  denom_key_issue.denom_hash = denom_key->h_key;
+  denom_key_issue.start = GNUNET_TIME_absolute_hton (denom_key->valid_from);
+  denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton 
(denom_key->withdraw_valid_until);
+  denom_key_issue.expire_deposit = GNUNET_TIME_absolute_hton 
(denom_key->expire_deposit);
+  denom_key_issue.expire_legal = GNUNET_TIME_absolute_hton 
(denom_key->expire_legal);
   TALER_amount_hton (&denom_key_issue.value,
-                     &value);
+                    &denom_key->value);
   TALER_amount_hton (&denom_key_issue.fee_withdraw,
-                     &fee_withdraw);
+                    &denom_key->fee_withdraw);
   TALER_amount_hton (&denom_key_issue.fee_deposit,
-                     &fee_deposit);
+                      &denom_key->fee_deposit);
   TALER_amount_hton (&denom_key_issue.fee_refresh,
-                     &fee_refresh);
+                    &denom_key->fee_refresh);
   TALER_amount_hton (&denom_key_issue.fee_refund,
-                     &fee_refund);
+                    &denom_key->fee_refund);
   EXITIF (GNUNET_SYSERR ==
-          GNUNET_CRYPTO_eddsa_verify 
(TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
-                                      &denom_key_issue.purpose,
-                                      &sig,
-                                      &master_key->eddsa_pub));
+         GNUNET_CRYPTO_eddsa_verify 
(TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
+                                     &denom_key_issue.purpose,
+                                     &sig,
+                                     &master_key->eddsa_pub));
   GNUNET_CRYPTO_hash_context_read (hash_context,
-                                   &denom_key_issue.denom_hash,
-                                   sizeof (struct GNUNET_HashCode));
-  denom_key->key.rsa_public_key = pk;
-  denom_key->h_key = denom_key_issue.denom_hash;
-  denom_key->valid_from = valid_from;
-  denom_key->withdraw_valid_until = withdraw_valid_until;
-  denom_key->expire_deposit = expire_deposit;
-  denom_key->expire_legal = expire_legal;
-  denom_key->value = value;
-  denom_key->fee_withdraw = fee_withdraw;
-  denom_key->fee_deposit = fee_deposit;
-  denom_key->fee_refresh = fee_refresh;
-  denom_key->fee_refund = fee_refund;
+                                  &denom_key_issue.denom_hash,
+                                  sizeof (struct GNUNET_HashCode));
   return GNUNET_OK;
 
  EXITIF_exit:
@@ -385,6 +378,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey 
*denom_key,
  * Parse a exchange's auditor information encoded in JSON.
  *
  * @param[out] auditor where to return the result
+ * @param check_sig should we check signatures
  * @param[in] auditor_obj json to parse
  * @param key_data information about denomination keys
  * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
@@ -392,6 +386,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey 
*denom_key,
  */
 static int
 parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
+                   int check_sigs,
                     json_t *auditor_obj,
                     const struct TALER_EXCHANGE_Keys *key_data)
 {
@@ -438,16 +433,18 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
     const struct TALER_EXCHANGE_DenomPublicKey *dk;
     unsigned int dk_off;
     struct GNUNET_JSON_Specification kspec[] = {
-      GNUNET_JSON_spec_fixed_auto ("denom_pub_h",
-                                   &denom_h),
       GNUNET_JSON_spec_fixed_auto ("auditor_sig",
                                    &auditor_sig),
+      /* auditor_sig must be first, as we skip it if 
+        'check_sigs' is false */
+      GNUNET_JSON_spec_fixed_auto ("denom_pub_h",
+                                   &denom_h),
       GNUNET_JSON_spec_end()
     };
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (key,
-                           kspec,
+                           (check_sigs) ? kspec : &kspec[1],
                            NULL, NULL))
     {
       GNUNET_break_op (0);
@@ -471,31 +468,34 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
       GNUNET_break_op (0);
       continue;
     }
-    kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
-    kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
-    kv.expire_deposit = GNUNET_TIME_absolute_hton (dk->expire_deposit);
-    kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
-    TALER_amount_hton (&kv.value,
-                       &dk->value);
-    TALER_amount_hton (&kv.fee_withdraw,
-                       &dk->fee_withdraw);
-    TALER_amount_hton (&kv.fee_deposit,
-                       &dk->fee_deposit);
-    TALER_amount_hton (&kv.fee_refresh,
-                       &dk->fee_refresh);
-    TALER_amount_hton (&kv.fee_refund,
-                       &dk->fee_refund);
-    kv.denom_hash = dk->h_key;
-
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS,
-                                    &kv.purpose,
-                                    &auditor_sig.eddsa_sig,
-                                    &auditor->auditor_pub.eddsa_pub))
+    if (check_sigs)
     {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (spec);
-      return GNUNET_SYSERR;
+      kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
+      kv.expire_withdraw = GNUNET_TIME_absolute_hton 
(dk->withdraw_valid_until);
+      kv.expire_deposit = GNUNET_TIME_absolute_hton (dk->expire_deposit);
+      kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
+      TALER_amount_hton (&kv.value,
+                       &dk->value);
+      TALER_amount_hton (&kv.fee_withdraw,
+                        &dk->fee_withdraw);
+      TALER_amount_hton (&kv.fee_deposit,
+                        &dk->fee_deposit);
+      TALER_amount_hton (&kv.fee_refresh,
+                        &dk->fee_refresh);
+      TALER_amount_hton (&kv.fee_refund,
+                        &dk->fee_refund);
+      kv.denom_hash = dk->h_key;
+      
+      if (GNUNET_OK !=
+         GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS,
+                                     &kv.purpose,
+                                     &auditor_sig.eddsa_sig,
+                                     &auditor->auditor_pub.eddsa_pub))
+      {
+       GNUNET_break_op (0);
+       GNUNET_JSON_parse_free (spec);
+       return GNUNET_SYSERR;
+      }
     }
     auditor->denom_key_offsets[off] = dk_off;
     off++;
@@ -511,12 +511,14 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
  * in the @a key_data.
  *
  * @param[in] resp_obj JSON object to parse
+ * @param check_sig #GNUNET_YES if we should check the signature
  * @param[out] key_data where to store the results we decoded
  * @param[out] where to store version compatibility data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON)
  */
 static int
 decode_keys_json (const json_t *resp_obj,
+                 int check_sig,
                   struct TALER_EXCHANGE_Keys *key_data,
                  enum TALER_EXCHANGE_VersionCompatibility *vc)
 {
@@ -529,6 +531,11 @@ decode_keys_json (const json_t *resp_obj,
   unsigned int age;
   unsigned int revision;
   unsigned int current;
+  struct GNUNET_JSON_Specification mspec[] = {
+    GNUNET_JSON_spec_fixed_auto ("master_public_key",
+                                &key_data->master_pub),
+    GNUNET_JSON_spec_end()
+  };
 
   if (JSON_OBJECT != json_typeof (resp_obj))
   {
@@ -577,29 +584,17 @@ decode_keys_json (const json_t *resp_obj,
     key_data->version = GNUNET_strdup (ver);
   }
 
-  /* parse the master public key and issue date of the response */
-  hash_context = GNUNET_CRYPTO_hash_context_start ();
-  {
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_fixed_auto ("master_public_key",
-                                   &key_data->master_pub),
-      GNUNET_JSON_spec_fixed_auto ("eddsa_sig",
-                                   &sig),
-      GNUNET_JSON_spec_fixed_auto ("eddsa_pub",
-                                   &pub),
-      GNUNET_JSON_spec_absolute_time ("list_issue_date",
-                                      &list_issue_date),
-      GNUNET_JSON_spec_relative_time ("reserve_closing_delay",
-                                      &key_data->reserve_closing_delay),
-      GNUNET_JSON_spec_end()
-    };
-
-    EXITIF (GNUNET_OK !=
-            GNUNET_JSON_parse (resp_obj,
-                               spec,
-                               NULL, NULL));
-  }
+  EXITIF (GNUNET_OK !=
+         GNUNET_JSON_parse (resp_obj,
+                            mspec,
+                            NULL, NULL));
 
+  /* parse the master public key and issue date of the response */
+  if (check_sig) 
+    hash_context = GNUNET_CRYPTO_hash_context_start ();
+  else
+    hash_context = NULL;
+  
   /* parse the signing keys */
   {
     json_t *sign_keys_array;
@@ -619,6 +614,7 @@ decode_keys_json (const json_t *resp_obj,
     json_array_foreach (sign_keys_array, index, sign_key_obj) {
       EXITIF (GNUNET_SYSERR ==
               parse_json_signkey (&key_data->sign_keys[index],
+                                 check_sig,
                                   sign_key_obj,
                                   &key_data->master_pub));
     }
@@ -644,6 +640,7 @@ decode_keys_json (const json_t *resp_obj,
 
       EXITIF (GNUNET_SYSERR ==
               parse_json_denomkey (&dk,
+                                  check_sig,
                                    denom_key_obj,
                                    &key_data->master_pub,
                                    hash_context));
@@ -684,7 +681,8 @@ decode_keys_json (const json_t *resp_obj,
     unsigned int index;
 
     EXITIF (NULL == (auditors_array =
-                     json_object_get (resp_obj, "auditors")));
+                     json_object_get (resp_obj,
+                                     "auditors")));
     EXITIF (JSON_ARRAY != json_typeof (auditors_array));
 
     /* Merge with the existing auditor information we have (/keys cherry 
picking) */
@@ -693,8 +691,12 @@ decode_keys_json (const json_t *resp_obj,
       struct TALER_EXCHANGE_AuditorInformation ai;
       bool found = false;
 
+      memset (&ai,
+             0,
+             sizeof (ai));
       EXITIF (GNUNET_SYSERR ==
               parse_json_auditor (&ai,
+                                 check_sig,
                                   auditor_info,
                                   key_data));
       for (unsigned int j=0;j<key_data->num_auditors;j++)
@@ -727,21 +729,58 @@ decode_keys_json (const json_t *resp_obj,
     };
   }
 
-  /* Validate signature... */
-  ks.purpose.size = htonl (sizeof (ks));
-  ks.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET);
-  ks.list_issue_date = GNUNET_TIME_absolute_hton (list_issue_date);
-  GNUNET_CRYPTO_hash_context_finish (hash_context,
-                                     &ks.hc);
-  hash_context = NULL;
-  EXITIF (GNUNET_OK !=
-          TALER_EXCHANGE_test_signing_key (key_data,
-                                          &pub));
-  EXITIF (GNUNET_OK !=
-          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
-                                      &ks.purpose,
-                                      &sig.eddsa_signature,
-                                      &pub.eddsa_pub));
+  if (check_sig)
+  {
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("eddsa_sig",
+                                   &sig),
+      GNUNET_JSON_spec_fixed_auto ("eddsa_pub",
+                                   &pub),
+      GNUNET_JSON_spec_absolute_time ("list_issue_date",
+                                      &list_issue_date),
+      GNUNET_JSON_spec_relative_time ("reserve_closing_delay",
+                                      &key_data->reserve_closing_delay),
+      GNUNET_JSON_spec_end()
+    };
+
+    EXITIF (GNUNET_OK !=
+            GNUNET_JSON_parse (resp_obj,
+                               spec,
+                               NULL, NULL));
+    /* Validate signature... */
+    ks.purpose.size = htonl (sizeof (ks));
+    ks.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET);
+    ks.list_issue_date = GNUNET_TIME_absolute_hton (list_issue_date);
+    GNUNET_CRYPTO_hash_context_finish (hash_context,
+                                      &ks.hc);
+    hash_context = NULL;
+    EXITIF (GNUNET_OK !=
+           TALER_EXCHANGE_test_signing_key (key_data,
+                                            &pub));
+    EXITIF (GNUNET_OK !=
+           GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
+                                       &ks.purpose,
+                                       &sig.eddsa_signature,
+                                       &pub.eddsa_pub));
+  }
+  else
+  {
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("master_public_key",
+                                   &key_data->master_pub),
+      GNUNET_JSON_spec_absolute_time ("list_issue_date",
+                                      &list_issue_date),
+      GNUNET_JSON_spec_relative_time ("reserve_closing_delay",
+                                      &key_data->reserve_closing_delay),
+      GNUNET_JSON_spec_end()
+    };
+
+    EXITIF (GNUNET_OK !=
+            GNUNET_JSON_parse (resp_obj,
+                               spec,
+                               NULL, NULL));
+  }
+  key_data->list_issue_date = list_issue_date;
   return GNUNET_OK;
  EXITIF_exit:
 
@@ -895,10 +934,27 @@ keys_completed_cb (void *cls,
 
     if (GNUNET_OK !=
         decode_keys_json (resp_obj,
+                         GNUNET_YES,
                           &kd,
                          &vc))
     {
       response_code = 0;
+      for (unsigned int i=0;i<kd.num_auditors;i++)
+      {
+       struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i];
+
+       GNUNET_array_grow (anew->denom_key_offsets,
+                          anew->num_denom_keys,
+                          0);
+       GNUNET_free (anew->auditor_url);
+      }
+      GNUNET_free (kd.auditors);
+      kd.auditors = NULL;
+      for (unsigned int i=0;i<kd_old.num_denom_keys;i++)
+       GNUNET_CRYPTO_rsa_public_key_free (kd.denom_keys[i].key.rsa_public_key);
+      GNUNET_array_grow (kd.denom_keys,
+                        kd.denom_keys_size,
+                        0);
       break;
     }
     json_decref (exchange->key_data_raw);
@@ -918,16 +974,16 @@ keys_completed_cb (void *cls,
     exchange->kr = NULL;
     free_keys_request (kr);
     exchange->state = MHS_FAILED;
-    /* notify application that we failed */
-    exchange->cert_cb (exchange->cert_cb_cls,
-                       NULL,
-                      vc);
     if (NULL != exchange->key_data_raw)
     {
       json_decref (exchange->key_data_raw);
       exchange->key_data_raw = NULL;
     }
     free_key_data (&kd_old);
+    /* notify application that we failed */
+    exchange->cert_cb (exchange->cert_cb_cls,
+                       NULL,
+                      vc);
     return;
   }
 
@@ -1117,8 +1173,11 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
   enum TALER_EXCHANGE_VersionCompatibility vc;
   json_t *keys;
   const char *url;
+  uint32_t version;
   struct GNUNET_TIME_Absolute expire;
   struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_uint32 ("version",
+                            &version),
     GNUNET_JSON_spec_json ("keys",
                           &keys),
     GNUNET_JSON_spec_string ("url",
@@ -1139,6 +1198,8 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
     GNUNET_break_op (0);
     return;
   }
+  if (0 != version)
+    return; /* unsupported version */
   if (0 != strcmp (url,
                   exchange->url))
     {
@@ -1150,6 +1211,7 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
           sizeof (struct TALER_EXCHANGE_Keys));
   if (GNUNET_OK !=
       decode_keys_json (keys,
+                       GNUNET_NO,
                        &key_data,
                        &vc))
     {
@@ -1181,7 +1243,152 @@ deserialize_data (struct TALER_EXCHANGE_Handle 
*exchange,
 json_t *
 TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
 {
-  return NULL;
+  const struct TALER_EXCHANGE_Keys *kd = &exchange->key_data;
+  struct GNUNET_TIME_Absolute now;
+  json_t *keys;
+  json_t *signkeys;
+  json_t *denoms;
+  json_t *auditors;
+
+  now = GNUNET_TIME_absolute_get ();
+  signkeys = json_array ();
+  for (unsigned int i=0;i<kd->num_sign_keys;i++)
+  {
+    const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i];
+    json_t *signkey;
+    
+    if (now.abs_value_us > sk->valid_until.abs_value_us)
+      continue; /* skip keys that have expired */
+    signkey = json_pack ("{s:o, s:o, s:o, s:o}",
+                        "key",
+                        GNUNET_JSON_from_data_auto (&sk->key),
+                        "stamp_start",
+                        GNUNET_JSON_from_time_abs (sk->valid_from),
+                        "stamp_expire",
+                        GNUNET_JSON_from_time_abs (sk->valid_until),
+                        "stamp_end",
+                        GNUNET_JSON_from_time_abs (sk->valid_legal));
+    if (NULL == signkey)
+    {
+      GNUNET_break (0);
+      continue;
+    }
+    json_array_append_new (signkeys,
+                          signkey);
+  }             
+  denoms = json_array ();
+  for (unsigned int i=0;i<kd->num_denom_keys;i++)
+  {
+    const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i];
+    json_t *denom;
+    
+    if (now.abs_value_us > dk->expire_deposit.abs_value_us)
+      continue; /* skip keys that have expired */
+    denom = json_pack ("{s:o, s:o, s:o, s:o, s:o "
+                      ",s:o, s:o, s:o, s:o, s:o}",
+                      "stamp_expire_deposit",
+                      GNUNET_JSON_from_time_abs (dk->expire_deposit),
+                      "stamp_expire_withdraw",
+                      GNUNET_JSON_from_time_abs (dk->withdraw_valid_until),
+                      "stamp_start",
+                      GNUNET_JSON_from_time_abs (dk->valid_from),
+                      "stamp_expire_legal",
+                      GNUNET_JSON_from_time_abs (dk->expire_legal),
+                      "value",
+                      TALER_JSON_from_amount (&dk->value),
+                      "fee_withdraw",
+                      /* #6 */
+                      TALER_JSON_from_amount (&dk->fee_withdraw),
+                      "fee_deposit",
+                      TALER_JSON_from_amount (&dk->fee_deposit),
+                      "fee_refresh",
+                      TALER_JSON_from_amount (&dk->fee_refresh),
+                      "fee_refund",
+                      TALER_JSON_from_amount (&dk->fee_refund),
+                      "denom_pub",
+                      GNUNET_JSON_from_rsa_public_key 
(dk->key.rsa_public_key));
+    if (NULL == denom)
+    {
+      GNUNET_break (0);
+      continue;
+    }
+    json_array_append_new (denoms,
+                          denom);
+  }             
+  auditors = json_array ();
+  for (unsigned int i=0;i<kd->num_auditors;i++)
+  {
+    const struct TALER_EXCHANGE_AuditorInformation *ai = &kd->auditors[i];
+    json_t *a;
+    json_t *adenoms; 
+
+    adenoms = json_array ();
+    for (unsigned int j=0;j<ai->num_denom_keys;j++)
+    {
+      unsigned int off = ai->denom_key_offsets[j];
+      const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[off];
+      json_t *k;
+
+      GNUNET_assert (off < kd->num_denom_keys);
+      k = json_pack ("{s:s}",
+                    "denom_pub_h",
+                    GNUNET_JSON_from_data_auto (&dk->h_key));
+      if (NULL == k)
+      {
+       GNUNET_break (0);
+       continue;
+      }
+      json_array_append_new (adenoms,
+                            k);
+    }
+    
+    a = json_pack ("{s:s, s:o, s:o}",
+                  "auditor_pub",
+                  GNUNET_JSON_from_data_auto (&ai->auditor_pub),
+                  "auditor_url",
+                  ai->auditor_url,
+                  "denomination_keys",
+                  adenoms);
+    if (NULL == a)
+    {
+      GNUNET_break (0);
+      continue;
+    }
+    json_array_append_new (auditors,
+                          a);
+  }             
+  keys = json_pack ("{s:s, s:o, s:o, s:o, s:o"
+                   ",s:o, s:o}",
+                   /* 1 */
+                   "version", 
+                   kd->version,
+                   "master_public_key",
+                   GNUNET_JSON_from_data_auto (&kd->master_pub),
+                   "reserve_closing_delay",
+                   GNUNET_JSON_from_time_rel (kd->reserve_closing_delay),
+                   "list_issue_date",
+                   GNUNET_JSON_from_time_abs (kd->list_issue_date),
+                   "signkeys",
+                   signkeys,
+                   /* #6 */
+                   "denoms",
+                   denoms,
+                   "auditors",
+                   auditors);
+  if (NULL == keys)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  return json_pack ("{s:I, s:o, s:s, s:o}",
+                   "version",
+                   (json_int_t) TALER_SERIALIZATION_FORMAT_VERSION,
+                   "expire",
+                   GNUNET_JSON_from_time_abs (exchange->key_data_expiration),
+                   "url",
+                   exchange->url,
+                   "keys",
+                   keys);
 }
 
 
@@ -1221,24 +1428,24 @@ TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx,
   va_start (ap, cert_cb_cls);
   while (TALER_EXCHANGE_OPTION_END !=
         (opt = va_arg (ap, int)))
+  {
+    switch (opt) {
+    case TALER_EXCHANGE_OPTION_END:
+      GNUNET_assert (0);
+      break;
+    case TALER_EXCHANGE_OPTION_DATA:
     {
-      switch (opt) {
-      case TALER_EXCHANGE_OPTION_END:
-       GNUNET_assert (0);
-       break;
-      case TALER_EXCHANGE_OPTION_DATA:
-       {
-         const json_t *data = va_arg (ap, const json_t *);
-
-         deserialize_data (exchange,
-                           data);
-         break;
-       }
-      default:
-       GNUNET_assert (0);
-       break;
-      }
+      const json_t *data = va_arg (ap, const json_t *);
+      
+      deserialize_data (exchange,
+                       data);
+      break;
+    }
+    default:
+      GNUNET_assert (0);
+      break;
     }
+  }
   va_end (ap);
   return exchange;
 }
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 6c2d342b..2e1a85f8 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -280,6 +280,26 @@ struct TEH_KS_StateHandle
 };
 
 
+
+/**
+ * Exchange key state.  This is the long-term, read-only internal global state,
+ * which the various threads "lock" to use in read-only ways.  We eventually
+ * create a completely new object "on the side" and then start to return
+ * the new read-only object to threads that ask. Once none of the threads
+ * use the previous object (RC drops to zero), we discard it.
+ *
+ * Thus, this instance should never be used directly, instead reserve
+ * access via #TEH_KS_acquire() and release it via #TEH_KS_release().
+ */
+static struct TEH_KS_StateHandle *internal_key_state;
+
+/**
+ * Mutex protecting access to #internal_key_state.
+ */
+static pthread_mutex_t internal_key_state_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+
 /* ************************** Clean up logic *********************** */
 
 
@@ -373,6 +393,10 @@ static void
 ks_release (struct TEH_KS_StateHandle *key_state)
 {
   GNUNET_assert (0 < key_state->refcnt);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "KS release called (%p/%d)\n",
+             key_state,
+             key_state->refcnt);
   key_state->refcnt--;
   if (0 == key_state->refcnt)
   {
@@ -404,6 +428,7 @@ ks_release (struct TEH_KS_StateHandle *key_state)
     GNUNET_array_grow (key_state->krd_array,
                        key_state->krd_array_length,
                        0);
+    GNUNET_assert (key_state != internal_key_state);
     GNUNET_free (key_state);
   }
 }
@@ -1604,25 +1629,6 @@ make_fresh_key_state ()
 /* ************************** Persistent part ********************** */
 
 /**
- * Exchange key state.  This is the long-term, read-only internal global state,
- * which the various threads "lock" to use in read-only ways.  We eventually
- * create a completely new object "on the side" and then start to return
- * the new read-only object to threads that ask. Once none of the threads
- * use the previous object (RC drops to zero), we discard it.
- *
- * Thus, this instance should never be used directly, instead reserve
- * access via #TEH_KS_acquire() and release it via #TEH_KS_release().
- */
-static struct TEH_KS_StateHandle *internal_key_state;
-
-/**
- * Mutex protecting access to #internal_key_state.
- */
-static pthread_mutex_t internal_key_state_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-
-/**
  * Release key state, free if necessary (if reference count gets to zero).
  *
  * @param location name of the function in which the lock is acquired
@@ -1634,8 +1640,10 @@ TEH_KS_release_ (const char *location,
 {
   GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "KS released at %s\n",
-              location);
+              "KS released at %s (%p/%d)\n",
+              location,
+             key_state,
+             key_state->refcnt);
   ks_release (key_state);
   GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex));
 }
@@ -1654,22 +1662,43 @@ TEH_KS_acquire_ (const char *location)
 {
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct TEH_KS_StateHandle *key_state;
+  unsigned int rcd;
 
   GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "KS acquired at %s\n",
-              location);
+  rcd = 0;
   if ( (NULL != internal_key_state) &&
        (internal_key_state->next_reload.abs_value_us <= now.abs_value_us) )
   {
-    ks_release (internal_key_state);
+    struct TEH_KS_StateHandle *ks = internal_key_state;
+    
     internal_key_state = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "KS released in acquire due to expiration\n");
+    ks_release (ks);
+    rcd = 1; /* remember that we released 'internal_key_state' */
   }
   if (NULL == internal_key_state)
+  {
     internal_key_state = make_fresh_key_state ();
+    /* bump RC by 1 if we released internal_key_state above */
+    internal_key_state->refcnt += rcd;
+  }
   key_state = internal_key_state;
   if (NULL != key_state)
+  {
     key_state->refcnt++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "KS acquired at %s (%p/%d)\n",
+               location,
+               key_state,
+               key_state->refcnt);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               "KS acquire failed at %s\n",
+               location);
+  }
   GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex));
 
   return key_state;
@@ -1876,8 +1905,10 @@ TEH_KS_loop (void)
                 "(re-)loading keys\n");
     if (NULL != internal_key_state)
     {
-      TEH_KS_release (internal_key_state);
+      struct TEH_KS_StateHandle *ks = internal_key_state;
+
       internal_key_state = NULL;
+      TEH_KS_release (ks);
     }
     /* This will re-initialize 'internal_key_state' with
        an initial refcnt of 1 */
@@ -1944,8 +1975,10 @@ TEH_KS_free ()
 {
   if (NULL != internal_key_state)
   {
-    TEH_KS_release (internal_key_state);
+    struct TEH_KS_StateHandle *ks = internal_key_state;
+    
     internal_key_state = NULL;
+    TEH_KS_release (ks);
   }
 }
 
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 1ddd7c13..4adb8591 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -68,9 +68,14 @@ struct TALER_EXCHANGE_SigningPublicKey
   struct GNUNET_TIME_Absolute valid_from;
 
   /**
-   * Validity expiration time
+   * Validity expiration time (how long the exchange may use it).
    */
   struct GNUNET_TIME_Absolute valid_until;
+
+  /**
+   * Validity expiration time for legal disputes.
+   */
+  struct GNUNET_TIME_Absolute valid_legal;
 };
 
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]