aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-07-01 14:15:26 +0200
committerChristian Grothoff <christian@grothoff.org>2017-07-01 14:15:26 +0200
commitd77c4160ecf7b1d33d49ba47e3236f5dcc14ecc8 (patch)
treee8c7f7de609003cf75eba19c50548df6b401046a
parentf048de97822f29ec3dae5de57fab7a72a1fc4d8a (diff)
implement logic to check protocol version compatibility (#5035)
-rw-r--r--src/benchmark/taler-exchange-benchmark.c4
-rw-r--r--src/exchange-lib/exchange_api_handle.c52
-rw-r--r--src/exchange-lib/test_exchange_api.c4
-rw-r--r--src/include/taler_exchange_service.h56
4 files changed, 109 insertions, 7 deletions
diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c
index 70cc014e7..10a5eed1b 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -1234,10 +1234,12 @@ build_refresh ()
*
* @param cls closure
* @param _keys information about keys of the exchange
+ * @param vc compatibility information
*/
static void
cert_cb (void *cls,
- const struct TALER_EXCHANGE_Keys *_keys)
+ const struct TALER_EXCHANGE_Keys *_keys,
+ enum TALER_EXCHANGE_VersionCompatibility vc)
{
/* check that keys is OK */
if (NULL == _keys)
diff --git a/src/exchange-lib/exchange_api_handle.c b/src/exchange-lib/exchange_api_handle.c
index 96ae45b37..a03f7d4ba 100644
--- a/src/exchange-lib/exchange_api_handle.c
+++ b/src/exchange-lib/exchange_api_handle.c
@@ -29,6 +29,17 @@
#include "taler_signatures.h"
#include "exchange_api_handle.h"
+/**
+ * Which revision of the Taler protocol is implemented
+ * by this library? Used to determine compatibility.
+ */
+#define TALER_PROTOCOL_CURRENT 0
+
+/**
+ * How many revisions back are we compatible to?
+ */
+#define TALER_PROTOCOL_AGE 0
+
/**
* Log error related to CURL operations.
@@ -485,11 +496,13 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
*
* @param[in] resp_obj JSON object to parse
* @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,
- struct TALER_EXCHANGE_Keys *key_data)
+ struct TALER_EXCHANGE_Keys *key_data,
+ enum TALER_EXCHANGE_VersionCompatibility *vc)
{
struct GNUNET_TIME_Absolute list_issue_date;
struct TALER_ExchangeSignatureP sig;
@@ -508,6 +521,9 @@ decode_keys_json (const json_t *resp_obj,
/* parse the master public key and issue date of the response */
{
const char *ver;
+ unsigned int age;
+ unsigned int revision;
+ unsigned int current;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("version",
&ver),
@@ -526,6 +542,29 @@ decode_keys_json (const json_t *resp_obj,
GNUNET_JSON_parse (resp_obj,
spec,
NULL, NULL));
+ if (3 != sscanf (ver,
+ "%u:%u:%u",
+ &current,
+ &revision,
+ &age))
+ {
+ GNUNET_break_op (0);
+ GNUNET_CRYPTO_hash_context_abort (hash_context);
+ return GNUNET_SYSERR;
+ }
+ *vc = TALER_EXCHANGE_VC_MATCH;
+ if (TALER_PROTOCOL_CURRENT < current)
+ {
+ *vc |= TALER_EXCHANGE_VC_NEWER;
+ if (TALER_PROTOCOL_CURRENT < current - age)
+ *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
+ }
+ if (TALER_PROTOCOL_CURRENT > current)
+ {
+ *vc |= TALER_EXCHANGE_VC_OLDER;
+ if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
+ *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
+ }
key_data->version = GNUNET_strdup (ver);
}
@@ -707,12 +746,14 @@ keys_completed_cb (void *cls,
struct TALER_EXCHANGE_Handle *exchange = kr->exchange;
struct TALER_EXCHANGE_Keys kd;
struct TALER_EXCHANGE_Keys kd_old;
+ enum TALER_EXCHANGE_VersionCompatibility vc;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received keys from URL `%s' with status %ld.\n",
kr->url,
response_code);
kd_old = exchange->key_data;
+ vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR;
switch (response_code)
{
case 0:
@@ -725,7 +766,8 @@ keys_completed_cb (void *cls,
}
if (GNUNET_OK !=
decode_keys_json (resp_obj,
- &kd))
+ &kd,
+ &vc))
{
response_code = 0;
break;
@@ -748,7 +790,8 @@ keys_completed_cb (void *cls,
exchange->state = MHS_FAILED;
/* notify application that we failed */
exchange->cert_cb (exchange->cert_cb_cls,
- NULL);
+ NULL,
+ vc);
if (NULL != exchange->key_data_raw)
{
json_decref (exchange->key_data_raw);
@@ -764,7 +807,8 @@ keys_completed_cb (void *cls,
exchange->state = MHS_CERT;
/* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls,
- &exchange->key_data);
+ &exchange->key_data,
+ vc);
free_key_data (&kd_old);
}
diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c
index 24b8f7e20..b5b68041e 100644
--- a/src/exchange-lib/test_exchange_api.c
+++ b/src/exchange-lib/test_exchange_api.c
@@ -3050,10 +3050,12 @@ do_shutdown (void *cls)
*
* @param cls closure
* @param keys information about keys of the exchange
+ * @param vc version compatibility
*/
static void
cert_cb (void *cls,
- const struct TALER_EXCHANGE_Keys *keys)
+ const struct TALER_EXCHANGE_Keys *keys,
+ enum TALER_EXCHANGE_VersionCompatibility vc)
{
struct InterpreterState *is = cls;
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 04fa51fff..487304c59 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -230,6 +230,58 @@ struct TALER_EXCHANGE_Keys
};
+/**
+ * How compatible are the protocol version of the exchange and this
+ * client? The bits (1,2,4) can be used to test if the exchange's
+ * version is incompatible, older or newer respectively.
+ */
+enum TALER_EXCHANGE_VersionCompatibility
+{
+
+ /**
+ * The exchange runs exactly the same protocol version.
+ */
+ TALER_EXCHANGE_VC_MATCH = 0,
+
+ /**
+ * The exchange is too old or too new to be compatible with this
+ * implementation (bit)
+ */
+ TALER_EXCHANGE_VC_INCOMPATIBLE = 1,
+
+ /**
+ * The exchange is older than this implementation (bit)
+ */
+ TALER_EXCHANGE_VC_OLDER = 2,
+
+ /**
+ * The exchange is too old to be compatible with
+ * this implementation.
+ */
+ TALER_EXCHANGE_VC_INCOMPATIBLE_OUTDATED
+ = TALER_EXCHANGE_VC_INCOMPATIBLE
+ | TALER_EXCHANGE_VC_OLDER,
+
+ /**
+ * The exchange is more recent than this implementation (bit).
+ */
+ TALER_EXCHANGE_VC_NEWER = 4,
+
+ /**
+ * The exchange is too recent for this implementation.
+ */
+ TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER
+ = TALER_EXCHANGE_VC_INCOMPATIBLE
+ | TALER_EXCHANGE_VC_NEWER,
+
+ /**
+ * We could not even parse the version data.
+ */
+ TALER_EXCHANGE_VC_PROTOCOL_ERROR = 8
+
+};
+
+
/**
* Function called with information about who is auditing
* a particular exchange and what key the exchange is using.
@@ -237,10 +289,12 @@ struct TALER_EXCHANGE_Keys
* @param cls closure
* @param keys information about the various keys used
* by the exchange, NULL if /keys failed
+ * @param compat protocol compatibility information
*/
typedef void
(*TALER_EXCHANGE_CertificationCallback) (void *cls,
- const struct TALER_EXCHANGE_Keys *keys);
+ const struct TALER_EXCHANGE_Keys *keys,
+ enum TALER_EXCHANGE_VersionCompatibility compat);
/**