diff options
Diffstat (limited to 'src/util/util.c')
-rw-r--r-- | src/util/util.c | 425 |
1 files changed, 411 insertions, 14 deletions
diff --git a/src/util/util.c b/src/util/util.c index 19924b89a..da5727487 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,25 +19,20 @@ * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Florian Dold * @author Benedikt Mueller + * @author Christian Grothoff */ #include "platform.h" #include "taler_util.h" +#include "taler_attributes.h" +#include <gnunet/gnunet_json_lib.h> +#include <unistr.h> -/** - * Convert a buffer to an 8-character string representative of the - * contents. This is used for logging binary data when debugging. - * - * @param buf buffer to log - * @param buf_size number of bytes in @a buf - * @return text representation of buf, valid until next - * call to this function - */ const char * TALER_b2s (const void *buf, size_t buf_size) { - static GNUNET_THREAD_LOCAL char ret[9]; + static TALER_THREAD_LOCAL char ret[9]; struct GNUNET_HashCode hc; char *tmp; @@ -46,13 +41,415 @@ TALER_b2s (const void *buf, &hc); tmp = GNUNET_STRINGS_data_to_string_alloc (&hc, sizeof (hc)); - memcpy (ret, - tmp, - 8); + GNUNET_memcpy (ret, + tmp, + 8); GNUNET_free (tmp); ret[8] = '\0'; return ret; } +void +TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo, + const struct TALER_DenomFeeSet *fees) +{ + TALER_amount_hton (&nbo->withdraw, + &fees->withdraw); + TALER_amount_hton (&nbo->deposit, + &fees->deposit); + TALER_amount_hton (&nbo->refresh, + &fees->refresh); + TALER_amount_hton (&nbo->refund, + &fees->refund); +} + + +void +TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees, + const struct TALER_DenomFeeSetNBOP *nbo) +{ + TALER_amount_ntoh (&fees->withdraw, + &nbo->withdraw); + TALER_amount_ntoh (&fees->deposit, + &nbo->deposit); + TALER_amount_ntoh (&fees->refresh, + &nbo->refresh); + TALER_amount_ntoh (&fees->refund, + &nbo->refund); +} + + +void +TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo, + const struct TALER_GlobalFeeSet *fees) +{ + TALER_amount_hton (&nbo->history, + &fees->history); + TALER_amount_hton (&nbo->account, + &fees->account); + TALER_amount_hton (&nbo->purse, + &fees->purse); +} + + +void +TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees, + const struct TALER_GlobalFeeSetNBOP *nbo) +{ + TALER_amount_ntoh (&fees->history, + &nbo->history); + TALER_amount_ntoh (&fees->account, + &nbo->account); + TALER_amount_ntoh (&fees->purse, + &nbo->purse); +} + + +void +TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo, + const struct TALER_WireFeeSet *fees) +{ + TALER_amount_hton (&nbo->wire, + &fees->wire); + TALER_amount_hton (&nbo->closing, + &fees->closing); +} + + +void +TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees, + const struct TALER_WireFeeSetNBOP *nbo) +{ + TALER_amount_ntoh (&fees->wire, + &nbo->wire); + TALER_amount_ntoh (&fees->closing, + &nbo->closing); +} + + +int +TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1, + const struct TALER_GlobalFeeSet *f2) +{ + int ret; + + ret = TALER_amount_cmp (&f1->history, + &f2->history); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->account, + &f2->account); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->purse, + &f2->purse); + if (0 != ret) + return ret; + return 0; +} + + +int +TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1, + const struct TALER_WireFeeSet *f2) +{ + int ret; + + ret = TALER_amount_cmp (&f1->wire, + &f2->wire); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->closing, + &f2->closing); + if (0 != ret) + return ret; + return 0; +} + + +enum GNUNET_GenericReturnValue +TALER_denom_fee_check_currency ( + const char *currency, + const struct TALER_DenomFeeSet *fees) +{ + if (GNUNET_YES != + TALER_amount_is_currency (&fees->withdraw, + currency)) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_YES != + TALER_amount_is_currency (&fees->deposit, + currency)) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_YES != + TALER_amount_is_currency (&fees->refresh, + currency)) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_YES != + TALER_amount_is_currency (&fees->refund, + currency)) + { + GNUNET_break (0); + return GNUNET_NO; + } + return GNUNET_OK; +} + + +/** + * Dump character in the low range into @a buf + * following RFC 8785. + * + * @param[in,out] buf buffer to modify + * @param val value to dump + */ +static void +lowdump (struct GNUNET_Buffer *buf, + unsigned char val) +{ + char scratch[7]; + + switch (val) + { + case 0x8: + GNUNET_buffer_write (buf, + "\\b", + 2); + break; + case 0x9: + GNUNET_buffer_write (buf, + "\\t", + 2); + break; + case 0xA: + GNUNET_buffer_write (buf, + "\\n", + 2); + break; + case 0xC: + GNUNET_buffer_write (buf, + "\\f", + 2); + break; + case 0xD: + GNUNET_buffer_write (buf, + "\\r", + 2); + break; + default: + GNUNET_snprintf (scratch, + sizeof (scratch), + "\\u%04x", + (unsigned int) val); + GNUNET_buffer_write (buf, + scratch, + 6); + break; + } +} + + +size_t +TALER_rfc8785encode (char **inp) +{ + struct GNUNET_Buffer buf = { 0 }; + size_t left = strlen (*inp) + 1; + size_t olen; + char *in = *inp; + const char *pos = in; + + GNUNET_buffer_prealloc (&buf, + left + 40); + buf.warn_grow = 0; /* disable, + 40 is just a wild guess */ + while (1) + { + int mbl = u8_mblen ((unsigned char *) pos, + left); + unsigned char val; + + if (0 == mbl) + break; + val = (unsigned char) *pos; + if ( (1 == mbl) && + (val <= 0x1F) ) + { + /* Should not happen, as input is produced by + * JSON stringification */ + GNUNET_break (0); + lowdump (&buf, + val); + } + else if ( (1 == mbl) && ('\\' == *pos) ) + { + switch (*(pos + 1)) + { + case '\\': + mbl = 2; + GNUNET_buffer_write (&buf, + pos, + mbl); + break; + case 'u': + { + unsigned int num; + uint32_t n32; + unsigned char res[8]; + size_t rlen; + + GNUNET_assert ( (1 == + sscanf (pos + 2, + "%4x", + &num)) || + (1 == + sscanf (pos + 2, + "%4X", + &num)) ); + mbl = 6; + n32 = (uint32_t) num; + rlen = sizeof (res); + u32_to_u8 (&n32, + 1, + res, + &rlen); + if ( (1 == rlen) && + (res[0] <= 0x1F) ) + { + lowdump (&buf, + res[0]); + } + else + { + GNUNET_buffer_write (&buf, + (const char *) res, + rlen); + } + } + break; + default: + mbl = 2; + GNUNET_buffer_write (&buf, + pos, + mbl); + break; + } + } + else + { + GNUNET_buffer_write (&buf, + pos, + mbl); + } + left -= mbl; + pos += mbl; + } + + /* 0-terminate buffer */ + GNUNET_buffer_write (&buf, + "", + 1); + GNUNET_free (in); + *inp = GNUNET_buffer_reap (&buf, + &olen); + return olen; +} + + +/** + * Hash normalized @a j JSON object or array and + * store the result in @a hc. + * + * @param j JSON to hash + * @param[out] hc where to write the hash + */ +void +TALER_json_hash (const json_t *j, + struct GNUNET_HashCode *hc) +{ + char *cstr; + size_t clen; + + cstr = json_dumps (j, + JSON_COMPACT | JSON_SORT_KEYS); + GNUNET_assert (NULL != cstr); + clen = TALER_rfc8785encode (&cstr); + GNUNET_CRYPTO_hash (cstr, + clen, + hc); + GNUNET_free (cstr); +} + + +#ifdef __APPLE__ +char * +strchrnul (const char *s, + int c) +{ + char *value; + value = strchr (s, + c); + if (NULL == value) + value = &s[strlen (s)]; + return value; +} + + +#endif + + +void +TALER_CRYPTO_attributes_to_kyc_prox ( + const json_t *attr, + struct GNUNET_ShortHashCode *kyc_prox) +{ + const char *name = NULL; + const char *birthdate = NULL; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string (TALER_ATTRIBUTE_FULL_NAME, + &name), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string (TALER_ATTRIBUTE_BIRTHDATE, + &birthdate), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (attr, + spec, + NULL, NULL)) + { + GNUNET_break (0); + memset (kyc_prox, + 0, + sizeof (*kyc_prox)); + return; + } + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf ( + kyc_prox, + sizeof (*kyc_prox), + name, + (NULL == name) + ? 0 + : strlen (name), + birthdate, + (NULL == birthdate) + ? 0 + : strlen (birthdate), + NULL, + 0)); +} + + /* end of util.c */ |