From 61752e033436d73c7a70bc12d5be4706f1595ab6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 20 Jun 2015 22:40:06 +0200 Subject: simplify /keys parser by using json parser interpreter --- src/mint-lib/mint_api_handle.c | 261 ++++++++++++----------------------------- src/mint-lib/mint_api_json.c | 129 ++++++++++++++++---- src/mint-lib/mint_api_json.h | 66 ++++++++++- src/util/json.c | 6 +- 4 files changed, 243 insertions(+), 219 deletions(-) (limited to 'src') diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c index bd7d00e6a..8a5212ae5 100644 --- a/src/mint-lib/mint_api_handle.c +++ b/src/mint-lib/mint_api_handle.c @@ -27,6 +27,7 @@ #include "taler_mint_service.h" #include "taler_signatures.h" #include "mint_api_context.h" +#include "mint_api_json.h" #include "mint_api_handle.h" @@ -229,29 +230,6 @@ free_keys_request (struct KeysRequest *kr) } -/** - * Parses the timestamp encoded as ASCII string as UNIX timstamp. - * FIXME: we might want to move this function into libtalerutil. - * - * @param[out] abs successfully parsed timestamp will be returned thru this parameter - * @param tstamp_enc the ASCII encoding of the timestamp - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -static int -parse_timestamp (struct GNUNET_TIME_Absolute *abs, - const char *tstamp_enc) -{ - unsigned long tstamp; - - if (1 != sscanf (tstamp_enc, "%lu", &tstamp)) - return GNUNET_SYSERR; - *abs = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get_zero_ (), - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, tstamp)); - return GNUNET_OK; -} - - #define EXITIF(cond) \ do { \ if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ @@ -272,110 +250,55 @@ parse_json_signkey (struct TALER_MINT_SigningPublicKey *sign_key, json_t *sign_key_obj, const struct TALER_MasterPublicKeyP *master_key) { - // TODO: try to simplify... - json_t *valid_from_obj; - json_t *valid_until_obj; - json_t *valid_legal_obj; - json_t *key_obj; - json_t *sig_obj; - const char *valid_from_enc; - const char *valid_until_enc; - const char *valid_legal_enc; - const char *key_enc; - const char *sig_enc; struct TALER_MintSigningKeyValidityPS 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 MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("master_sig", + &sig), + MAJ_spec_fixed_auto ("key", + &sign_key_issue.signkey_pub), + MAJ_spec_absolute_time ("stamp_start", + &valid_from), + MAJ_spec_absolute_time ("stamp_expire", + &valid_until), + MAJ_spec_absolute_time ("stamp_end", + &valid_legal), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (sign_key_obj, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } - EXITIF (JSON_OBJECT != json_typeof (sign_key_obj)); - EXITIF (NULL == (valid_from_obj = json_object_get (sign_key_obj, - "stamp_start"))); - EXITIF (NULL == (valid_until_obj = json_object_get (sign_key_obj, - "stamp_expire"))); - EXITIF (NULL == (valid_legal_obj = json_object_get (sign_key_obj, - "stamp_end"))); - EXITIF (NULL == (key_obj = json_object_get (sign_key_obj, "key"))); - EXITIF (NULL == (sig_obj = json_object_get (sign_key_obj, "master_sig"))); - EXITIF (NULL == (valid_from_enc = json_string_value (valid_from_obj))); - EXITIF (NULL == (valid_until_enc = json_string_value (valid_until_obj))); - EXITIF (NULL == (valid_legal_enc = json_string_value (valid_legal_obj))); - EXITIF (NULL == (key_enc = json_string_value (key_obj))); - EXITIF (NULL == (sig_enc = json_string_value (sig_obj))); - EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_from, - valid_from_enc)); - EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_until, - valid_until_enc)); - EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_legal, - valid_legal_enc)); - EXITIF (52 != strlen (key_enc)); /* strlen(base32(char[32])) = 52 */ - EXITIF (103 != strlen (sig_enc)); /* strlen(base32(char[64])) = 103 */ - EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (sig_enc, 103, - &sig, sizeof (sig))); - memset (&sign_key_issue, - 0, - sizeof (sign_key_issue)); - EXITIF (GNUNET_SYSERR == - GNUNET_CRYPTO_eddsa_public_key_from_string (key_enc, - 52, - &sign_key_issue.signkey_pub.eddsa_pub)); sign_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY); sign_key_issue.purpose.size = htonl (sizeof (sign_key_issue) - - offsetof (struct TALER_MintSigningKeyValidityPS, purpose)); + - offsetof (struct TALER_MintSigningKeyValidityPS, + 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); - EXITIF (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY, - &sign_key_issue.purpose, - &sig, - &master_key->eddsa_pub)); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY, + &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; - - EXITIF_exit: - return GNUNET_SYSERR; -} - - -/** - * Parse an amount given in JSON encoding. - * - * @param[in] amount_obj the amount in json - * @param[out] where to return the parsed amount - * @return #GNUNET_OK if all is well, #GNUNET_SYSERR on parse errors - */ -static int -parse_json_amount (json_t *amount_obj, - struct TALER_Amount *amt) -{ - // FIXME: check for correctness... - json_t *obj; - const char *currency_str; - int value; // FIXME: bad data type! (64 bit!) - int fraction; - - EXITIF (NULL == (obj = json_object_get (amount_obj, "currency"))); - EXITIF (NULL == (currency_str = json_string_value (obj))); - EXITIF (NULL == (obj = json_object_get (amount_obj, "value"))); - EXITIF (JSON_INTEGER != json_typeof (obj)); - EXITIF (0 > (value = json_integer_value (obj))); - EXITIF (NULL == (obj = json_object_get (amount_obj, "fraction"))); - EXITIF (JSON_INTEGER != json_typeof (obj)); - EXITIF (0 > (fraction = json_integer_value (obj))); - (void) memset (amt->currency, 0, sizeof (amt->currency)); - (void) strncpy (amt->currency, currency_str, sizeof (amt->currency) - 1); - amt->value = (uint32_t) value; - amt->fraction = (uint32_t) fraction; - return GNUNET_OK; - - EXITIF_exit: - return GNUNET_SYSERR; } @@ -393,16 +316,6 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key, json_t *denom_key_obj, struct TALER_MasterPublicKeyP *master_key) { - // FIXME: check logic, try to simplify - json_t *obj; - const char *sig_enc; - const char *deposit_valid_until_enc; - const char *withdraw_valid_until_enc; - const char *valid_from_enc; - const char *expire_legal_enc; - const char *key_enc; - char *buf; - size_t buf_size; struct GNUNET_TIME_Absolute valid_from; struct GNUNET_TIME_Absolute withdraw_valid_until; struct GNUNET_TIME_Absolute deposit_valid_until; @@ -415,55 +328,38 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key, struct GNUNET_CRYPTO_rsa_PublicKey *pk; struct GNUNET_CRYPTO_EddsaSignature sig; - EXITIF (JSON_OBJECT != json_typeof (denom_key_obj)); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "master_sig"))); - EXITIF (NULL == (sig_enc = json_string_value (obj))); - EXITIF (103 != strlen (sig_enc)); - EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (sig_enc, 103, - &sig, sizeof (sig))); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_expire_deposit"))); - EXITIF (NULL == (deposit_valid_until_enc = json_string_value (obj))); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_expire_withdraw"))); - EXITIF (NULL == (withdraw_valid_until_enc = json_string_value (obj))); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_start"))); - EXITIF (NULL == (valid_from_enc = json_string_value (obj))); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_expire_legal"))); - EXITIF (NULL == (expire_legal_enc = json_string_value (obj))); - - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "denom_pub"))); - EXITIF (NULL == (key_enc = json_string_value (obj))); - - EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_from, valid_from_enc)); - EXITIF (GNUNET_SYSERR == parse_timestamp (&withdraw_valid_until, - withdraw_valid_until_enc)); - EXITIF (GNUNET_SYSERR == parse_timestamp (&deposit_valid_until, - deposit_valid_until_enc)); - EXITIF (GNUNET_SYSERR == parse_timestamp (&expire_legal, - expire_legal_enc)); + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("master_sig", + &sig), + MAJ_spec_absolute_time ("stamp_expire_deposit", + &deposit_valid_until), + MAJ_spec_absolute_time ("stamp_expire_withdraw", + &withdraw_valid_until), + MAJ_spec_absolute_time ("stamp_start", + &valid_from), + MAJ_spec_absolute_time ("stamp_expire_legal", + &expire_legal), + MAJ_spec_amount ("value", + &value), + MAJ_spec_amount ("fee_withdraw", + &fee_withdraw), + MAJ_spec_amount ("fee_deposit", + &fee_deposit), + MAJ_spec_amount ("fee_refresh", + &fee_refresh), + MAJ_spec_rsa_public_key ("denom_pub", + &pk), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (denom_key_obj, + spec)) + return GNUNET_SYSERR; memset (&denom_key_issue, 0, sizeof (denom_key_issue)); - - buf_size = (strlen (key_enc) * 5) / 8; - buf = GNUNET_malloc (buf_size); - - EXITIF (GNUNET_OK != - GNUNET_STRINGS_string_to_data (key_enc, strlen (key_enc), - buf, - buf_size)); - pk = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); - GNUNET_free (buf); - - EXITIF (NULL == pk); GNUNET_CRYPTO_rsa_public_key_hash (pk, &denom_key_issue.denom_hash); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "value"))); - EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &value)); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_withdraw"))); - EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_withdraw)); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_deposit"))); - EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_deposit)); - EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_refresh"))); - EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_refresh)); denom_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY); denom_key_issue.purpose.size @@ -499,6 +395,7 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key, return GNUNET_OK; EXITIF_exit: + MAJ_parse_free (spec); return GNUNET_SYSERR; } @@ -520,33 +417,19 @@ decode_keys_json (json_t *resp_obj, if (JSON_OBJECT != json_typeof (resp_obj)) return GNUNET_SYSERR; - /* parse the master public key */ + /* parse the master public key and issue date of the response */ { - json_t *master_key_obj; - const char *master_key_enc; + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("master_public_key", + &key_data->master_pub), + MAJ_spec_absolute_time ("list_issue_date", + &list_issue_date), + MAJ_spec_end + }; - EXITIF (NULL == (master_key_obj = - json_object_get (resp_obj, - "master_public_key"))); - EXITIF (NULL == (master_key_enc = - json_string_value (master_key_obj))); EXITIF (GNUNET_OK != - GNUNET_CRYPTO_eddsa_public_key_from_string (master_key_enc, - strlen (master_key_enc), - &key_data->master_pub.eddsa_pub)); - } - - /* parse the issue date of the response */ - { - json_t *list_issue_date_obj; - const char *tstamp_enc; - - EXITIF (NULL == (list_issue_date_obj = - json_object_get (resp_obj, - "list_issue_date"))); - EXITIF (NULL == (tstamp_enc = json_string_value (list_issue_date_obj))); - EXITIF (GNUNET_SYSERR == parse_timestamp (&list_issue_date, - tstamp_enc)); + MAJ_parse_json (resp_obj, + spec)); } /* parse the signing keys */ diff --git a/src/mint-lib/mint_api_json.c b/src/mint-lib/mint_api_json.c index b2757f115..75010a4d1 100644 --- a/src/mint-lib/mint_api_json.c +++ b/src/mint-lib/mint_api_json.c @@ -72,9 +72,9 @@ parse_time_abs (json_t *f, GNUNET_break_op (0); return GNUNET_SYSERR; } - /* Time is in 'ms' in JSON, but in microseconds in GNUNET_TIME_Absolute */ - time->abs_value_us = tval * 1000LL; - if ( (time->abs_value_us) / 1000LL != tval) + /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ + time->abs_value_us = tval * 1000LL * 1000LL; + if ( (time->abs_value_us) / 1000LL / 1000LL != tval) { /* Integer overflow */ GNUNET_break_op (0); @@ -189,7 +189,7 @@ parse_json (json_t *root, } res = GNUNET_STRINGS_string_to_data (str, strlen (str), spec[i].details.fixed_data.dest, - spec[i].details.fixed_data.dest_len); + spec[i].details.fixed_data.dest_size); if (GNUNET_OK != res) { GNUNET_break_op (0); @@ -201,7 +201,7 @@ parse_json (json_t *root, case MAJ_CMD_BINARY_VARIABLE: { const char *str; - size_t len; + size_t size; void *data; int res; @@ -211,16 +211,17 @@ parse_json (json_t *root, GNUNET_break_op (0); return i; } - len = (strlen (str) * 5) / 8; - if (len >= 1024) + size = (strlen (str) * 5) / 8; + if (size >= 1024) { GNUNET_break_op (0); return i; } - data = GNUNET_malloc (len); - res = GNUNET_STRINGS_string_to_data (str, strlen (str), + data = GNUNET_malloc (size); + res = GNUNET_STRINGS_string_to_data (str, + strlen (str), data, - len); + size); if (GNUNET_OK != res) { GNUNET_break_op (0); @@ -228,13 +229,13 @@ parse_json (json_t *root, return i; } *spec[i].details.variable_data.dest_p = data; - *spec[i].details.variable_data.dest_len_p = len; + *spec[i].details.variable_data.dest_size_p = size; } break; case MAJ_CMD_RSA_PUBLIC_KEY: { - size_t len; + size_t size; const char *str; int res; void *buf; @@ -245,12 +246,12 @@ parse_json (json_t *root, GNUNET_break_op (0); return i; } - len = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (len); + size = (strlen (str) * 5) / 8; + buf = GNUNET_malloc (size); res = GNUNET_STRINGS_string_to_data (str, strlen (str), buf, - len); + size); if (GNUNET_OK != res) { GNUNET_free (buf); @@ -259,7 +260,7 @@ parse_json (json_t *root, } *spec[i].details.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_decode (buf, - len); + size); GNUNET_free (buf); if (NULL == spec[i].details.rsa_public_key) { @@ -271,7 +272,7 @@ parse_json (json_t *root, case MAJ_CMD_RSA_SIGNATURE: { - size_t len; + size_t size; const char *str; int res; void *buf; @@ -282,12 +283,12 @@ parse_json (json_t *root, GNUNET_break_op (0); return i; } - len = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (len); + size = (strlen (str) * 5) / 8; + buf = GNUNET_malloc (size); res = GNUNET_STRINGS_string_to_data (str, strlen (str), buf, - len); + size); if (GNUNET_OK != res) { GNUNET_free (buf); @@ -296,7 +297,7 @@ parse_json (json_t *root, } *spec[i].details.rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (buf, - len); + size); GNUNET_free (buf); if (NULL == spec[i].details.rsa_signature) return i; @@ -341,7 +342,7 @@ parse_free (struct MAJ_Specification *spec, case MAJ_CMD_BINARY_VARIABLE: GNUNET_free (*spec[i].details.variable_data.dest_p); *spec[i].details.variable_data.dest_p = NULL; - *spec[i].details.variable_data.dest_len_p = 0; + *spec[i].details.variable_data.dest_size_p = 0; break; case MAJ_CMD_RSA_PUBLIC_KEY: GNUNET_CRYPTO_rsa_public_key_free (*spec[i].details.rsa_public_key); @@ -377,8 +378,9 @@ MAJ_parse_json (const json_t *root, if (-1 == ret) return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "JSON field `%s` had unexpected value\n", - spec[ret].field); + "JSON field `%s` (%d) had unexpected value\n", + spec[ret].field, + ret); parse_free (spec, ret); return GNUNET_SYSERR; } @@ -400,5 +402,84 @@ MAJ_parse_free (struct MAJ_Specification *spec) } +/** + * Specification for parsing an absolute time value. + * + * @param name name of the JSON field + * @param at where to store the absolute time found under @a name + */ +struct MAJ_Specification +MAJ_spec_absolute_time (const char *name, + struct GNUNET_TIME_Absolute *at) +{ + struct MAJ_Specification ret = + { + .cmd = MAJ_CMD_TIME_ABSOLUTE, + .field = name, + .details.abs_time = at + }; + return ret; +} + + +/** + * Specification for parsing an amount value. + * + * @param name name of the JSON field + * @param at where to store the absolute time found under @a name + */ +struct MAJ_Specification +MAJ_spec_amount (const char *name, + struct TALER_Amount *amount) +{ + struct MAJ_Specification ret = + { + .cmd = MAJ_CMD_AMOUNT, + .field = name, + .details.amount = amount + }; + return ret; +} + + +/** + * Specification for parsing an RSA public key. + * + * @param name name of the JSON field + * @param pk where to store the RSA key found under @a name + */ +struct MAJ_Specification +MAJ_spec_rsa_public_key (const char *name, + struct GNUNET_CRYPTO_rsa_PublicKey **pk) +{ + struct MAJ_Specification ret = + { + .cmd = MAJ_CMD_AMOUNT, + .field = name, + .details.rsa_public_key = pk + }; + return ret; +} + + +/** + * Specification for parsing an RSA signature. + * + * @param name name of the JSON field + * @param sig where to store the RSA signature found under @a name + */ +struct MAJ_Specification +MAJ_spec_rsa_signature (const char *name, + struct GNUNET_CRYPTO_rsa_Signature **sig) +{ + struct MAJ_Specification ret = + { + .cmd = MAJ_CMD_AMOUNT, + .field = name, + .details.rsa_signature = sig + }; + return ret; +} + /* end of mint_api_json.c */ diff --git a/src/mint-lib/mint_api_json.h b/src/mint-lib/mint_api_json.h index 87afbd44b..78107ed9e 100644 --- a/src/mint-lib/mint_api_json.h +++ b/src/mint-lib/mint_api_json.h @@ -129,7 +129,7 @@ struct MAJ_Specification /** * How many bytes to write to @e dest. */ - size_t dest_len; + size_t dest_size; } fixed_data; @@ -145,7 +145,7 @@ struct MAJ_Specification /** * Where to store the number of bytes allocated at `*dest`. */ - size_t *dest_len_p; + size_t *dest_size_p; } variable_data; @@ -164,7 +164,6 @@ struct MAJ_Specification }; - /** * Navigate and parse data in a JSON tree. * @@ -187,4 +186,65 @@ void MAJ_parse_free (struct MAJ_Specification *spec); +/** + * End of a parser specification. + */ +#define MAJ_spec_end { .cmd = MAJ_CMD_END } + +/** + * Fixed size object (in network byte order, encoded using Crockford + * Base32hex encoding). + * + * @param name name of the JSON field + * @param obj pointer where to write the data (type of `*obj` will determine size) + */ +#define MAJ_spec_fixed_auto(name,obj) { .cmd = MAJ_CMD_BINARY_FIXED, .field = name, .details.fixed_data.dest = obj, .details.fixed_data.dest_size = sizeof (*obj) } + + +/** + * Absolute time. + * + * @param name name of the JSON field + * @param at where to store the absolute time found under @a name + */ +struct MAJ_Specification +MAJ_spec_absolute_time (const char *name, + struct GNUNET_TIME_Absolute *at); + + +/** + * Specification for parsing an amount value. + * + * @param name name of the JSON field + * @param at where to store the absolute time found under @a name + */ +struct MAJ_Specification +MAJ_spec_amount (const char *name, + struct TALER_Amount *amount); + + +/** + * Specification for parsing an RSA public key. + * + * @param name name of the JSON field + * @param pk where to store the RSA key found under @a name + */ +struct MAJ_Specification +MAJ_spec_rsa_public_key (const char *name, + struct GNUNET_CRYPTO_rsa_PublicKey **pk); + + +/** + * Specification for parsing an RSA signature. + * + * @param name name of the JSON field + * @param sig where to store the RSA signature found under @a name + */ +struct MAJ_Specification +MAJ_spec_rsa_signature (const char *name, + struct GNUNET_CRYPTO_rsa_Signature **sig); + + + + /* end of mint_api_json.h */ diff --git a/src/util/json.c b/src/util/json.c index e35b88a8f..d72840ebe 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -92,8 +92,8 @@ TALER_json_from_abs (struct GNUNET_TIME_Absolute stamp) if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) return json_string ("never"); ret = GNUNET_asprintf (&mystr, - "%llu", - (long long) (stamp.abs_value_us / (1000 * 1000))); + "/%llu/", + (long long) (stamp.abs_value_us / (1000LL * 1000LL))); GNUNET_assert (ret > 0); j = json_string (mystr); GNUNET_free (mystr); @@ -330,7 +330,7 @@ TALER_json_to_abs (json_t *json, return GNUNET_OK; } EXITIF (1 > sscanf (str, "%llu", &abs_value_s)); - abs->abs_value_us = abs_value_s * 1000 * 1000; + abs->abs_value_us = abs_value_s * 1000LL * 1000LL; return GNUNET_OK; EXITIF_exit: -- cgit v1.2.3