diff options
-rw-r--r-- | src/include/taler_signatures.h | 40 | ||||
-rw-r--r-- | src/include/taler_util.h | 19 | ||||
-rw-r--r-- | src/mint/mint.h | 189 | ||||
-rw-r--r-- | src/mint/mint_common.c | 30 | ||||
-rw-r--r-- | src/mint/mint_db.c | 10 | ||||
-rw-r--r-- | src/mint/taler-mint-dbinit.c | 17 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.c | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 5 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_deposit.c | 67 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_parsing.c | 84 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_parsing.h | 18 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 20 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 12 | ||||
-rw-r--r-- | src/mint/taler-mint-keycheck.c | 3 | ||||
-rw-r--r-- | src/mint/taler-mint-keyup.c | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-reservemod.c | 23 | ||||
-rw-r--r-- | src/mint/test_mint_deposits.c | 7 | ||||
-rw-r--r-- | src/util/util.c | 31 |
18 files changed, 400 insertions, 179 deletions
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 90fa421c3..e72c2ed61 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -29,6 +29,7 @@ #define TALER_SIGNATURES_H #include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" /** * Purpose for signing public keys signed @@ -141,6 +142,45 @@ struct TALER_WithdrawRequest }; +/** + * Format used to generate the signature on a request to deposit + * a coin into the account of a merchant. + */ +struct TALER_DepositRequest +{ + /** + * Purpose must be #TALER_SIGNATURE_DEPOSIT + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Hash over the contract for which this deposit is made. + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash over the wiring information of the merchant. + */ + struct GNUNET_HashCode h_wire; + + /** + * Merchant-generated transaction ID to detect duplicate + * transactions. + */ + uint64_t transaction_id GNUNET_PACKED; + + /** + * Amount to be deposited. + */ + struct TALER_AmountNBO amount; + + /** + * The coin's public key. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + +}; + /** * FIXME diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 2c5faaa52..ab5ee11df 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -73,14 +73,27 @@ void TALER_gcrypt_init (void); +/** + * Load configuration by parsing all configuration + * files in the given directory. + * + * @param base_dir directory with the configuration files + * @return NULL on error, otherwise configuration + */ +struct GNUNET_CONFIGURATION_Handle * +TALER_config_load (const char *base_dir); + + + /* *********************** Amount management ****************** */ /** * Number of characters (plus 1 for 0-termination) we use to - * represent currency names (i.e. EUR, USD, etc.). + * represent currency names (i.e. EUR, USD, etc.). We use + * 8 for alignment (!). */ -#define TALER_CURRENCY_LEN 4 +#define TALER_CURRENCY_LEN 8 GNUNET_NETWORK_STRUCT_BEGIN @@ -127,7 +140,7 @@ struct TALER_Amount /** * Currency string, left adjusted and padded with zeros. */ - char currency[4]; + char currency[TALER_CURRENCY_LEN]; }; diff --git a/src/mint/mint.h b/src/mint/mint.h index 05e966e1c..0a0e00d04 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -35,6 +35,11 @@ #define DIR_SIGNKEYS "signkeys" #define DIR_DENOMKEYS "denomkeys" +/** + * For now, we just do EUR. Should become configurable + * in the future! + */ +#define MINT_CURRENCY "EUR" /** * On disk format used for a mint signing key. @@ -63,7 +68,9 @@ struct TALER_MINT_DenomKeyIssuePriv /** - * Public information about a coin. + * Public information about a coin (including the public key + * of the coin, the denomination key and the signature with + * the denomination key). */ struct TALER_CoinPublicInfo { @@ -119,6 +126,92 @@ struct CollectableBlindcoin /** + * Specification for a /deposit operation. + */ +struct Deposit +{ + /** + * Information about the coin that is being deposited. + */ + struct TALER_CoinPublicInfo coin; + + /** + * ECDSA signature affirming that the customer intends + * this coin to be deposited at the merchant identified + * by @e h_wire in relation to the contract identified + * by @e h_contract. + */ + struct GNUNET_CRYPTO_EcdsaSignature csig; + + /** + * Public key of the merchant. Enables later identification + * of the merchant in case of a need to rollback transactions. + */ + struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; + + /** + * Hash over the contract between merchant and customer + * (remains unknown to the Mint). + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash of the (canonical) representation of @e wire, used + * to check the signature on the request. Generated by + * the mint from the detailed wire data provided by the + * merchant. + */ + struct GNUNET_HashCode h_wire; + + /** + * Detailed wire information for executing the transaction. + */ + const json_t *wire; + + /** + * Merchant-generated transaction ID to detect duplicate + * transactions. + */ + uint64_t transaction_id; + + /** + * Fraction of the coin's remaining value to be deposited. + * The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount; + + /** + * Type of the deposit (also purpose of the signature). Either + * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT. + */ + uint32_t purpose; // FIXME: bad type, use ENUM! + + +}; + + + +/** + * FIXME + */ +struct KnownCoin +{ + struct TALER_CoinPublicInfo public_info; + + /** + * Refreshing session, only valid if + * is_refreshed==1. + */ + struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; + + struct TALER_Amount expended_balance; + + int is_refreshed; + +}; + + +/** * Global information for a refreshing session. */ struct RefreshSession @@ -168,6 +261,9 @@ struct RefreshSession }; + + + /** * For each (old) coin being melted, we have a `struct * RefreshCommitLink` that allows the user to find the shared secret @@ -214,89 +310,8 @@ struct RefreshCommitCoin }; -/** - * FIXME - */ -struct KnownCoin -{ - struct TALER_CoinPublicInfo public_info; - - /** - * Refreshing session, only valid if - * is_refreshed==1. - */ - struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; - - struct TALER_Amount expended_balance; - int is_refreshed; -}; - - -/** - * Specification for a /deposit operation. - */ -struct Deposit -{ - /** - * Information about the coin that is being deposited. - */ - struct TALER_CoinPublicInfo coin; - - /** - * EdDSA signature affirming that the customer intends - * this coin to be deposited at the merchant identified - * by @e h_wire in relation to the contract identified - * by @e h_contract. - */ - struct GNUNET_CRYPTO_EddsaSignature csig; - - /** - * Public key of the merchant. Enables later identification - * of the merchant in case of a need to rollback transactions. - */ - struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; - - /** - * Hash over the contract between merchant and customer - * (remains unknown to the Mint). - */ - struct GNUNET_HashCode h_contract; - - /** - * Hash of the (canonical) representation of @e wire, used - * to check the signature on the request. Generated by - * the mint from the detailed wire data provided by the - * merchant. - */ - struct GNUNET_HashCode h_wire; - - /** - * Detailed wire information for executing the transaction. - */ - const json_t *wire; - - /** - * Merchant-generated transaction ID to detect duplicate - * transactions. - */ - uint64_t transaction_id; - - /** - * Fraction of the coin's remaining value to be deposited. - * The coin is identified by @e coin_pub. - */ - struct TALER_AmountNBO amount; - - /** - * Type of the deposit (also purpose of the signature). Either - * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT. - */ - uint32_t purpose; // FIXME: bad type, use ENUM! - - -}; /** @@ -412,16 +427,6 @@ TALER_MINT_read_denom_key (const char *filename, struct TALER_MINT_DenomKeyIssuePriv *dki); -/** - * Load the configuration for the mint in the given - * directory. - * - * @param mint_base_dir the mint's base directory - * @return the mint configuratin, or NULL on error - */ -struct GNUNET_CONFIGURATION_Handle * -TALER_MINT_config_load (const char *mint_base_dir); - int TALER_TALER_DB_extract_amount (PGresult *result, diff --git a/src/mint/mint_common.c b/src/mint/mint_common.c index bb55f30c4..f0ee09110 100644 --- a/src/mint/mint_common.c +++ b/src/mint/mint_common.c @@ -231,27 +231,11 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, } -struct GNUNET_CONFIGURATION_Handle * -TALER_MINT_config_load (const char *mint_base_dir) -{ - struct GNUNET_CONFIGURATION_Handle *cfg; - char *cfg_dir; - int res; - - res = GNUNET_asprintf (&cfg_dir, "%s" DIR_SEPARATOR_STR "config", mint_base_dir); - GNUNET_assert (res > 0); - - cfg = GNUNET_CONFIGURATION_create (); - res = GNUNET_CONFIGURATION_load_from (cfg, cfg_dir); - GNUNET_free (cfg_dir); - if (GNUNET_OK != res) - return NULL; - return cfg; -} - int -TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row, - int indices[3], struct TALER_AmountNBO *denom_nbo) +TALER_TALER_DB_extract_amount_nbo (PGresult *result, + unsigned int row, + int indices[3], + struct TALER_AmountNBO *denom_nbo) { if ((indices[0] < 0) || (indices[1] < 0) || (indices[2] < 0)) return GNUNET_NO; @@ -270,8 +254,10 @@ TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row, int -TALER_TALER_DB_extract_amount (PGresult *result, unsigned int row, - int indices[3], struct TALER_Amount *denom) +TALER_TALER_DB_extract_amount (PGresult *result, + unsigned int row, + int indices[3], + struct TALER_Amount *denom) { struct TALER_AmountNBO denom_nbo; int res; diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 4c836bf92..c07490805 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1925,11 +1925,11 @@ TALER_MINT_DB_get_deposit (PGconn *db_conn, EXITIF (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)); EXITIF (GNUNET_OK != - TALER_DB_extract_amount_nbo (result, 0, - "amount_value", - "amount_fraction", - "amount_currency", - &deposit->amount)); + TALER_DB_extract_amount (result, 0, + "amount_value", + "amount_fraction", + "amount_currency", + &deposit->amount)); deposit->coin.denom_sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_buf, denom_sig_buf_size); diff --git a/src/mint/taler-mint-dbinit.c b/src/mint/taler-mint-dbinit.c index d877f62c6..3d080b523 100644 --- a/src/mint/taler-mint-dbinit.c +++ b/src/mint/taler-mint-dbinit.c @@ -95,7 +95,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) } PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_sessions " "(" " session_pub BYTEA PRIMARY KEY CHECK (length(session_pub) = 32)" @@ -113,7 +113,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) } PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_order " "( " " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" @@ -130,7 +130,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_commit_link" "(" " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" @@ -150,7 +150,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) } PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_commit_coin" "(" " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " @@ -169,7 +169,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) } PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_melt" "(" " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " @@ -185,7 +185,7 @@ TALER_MINT_init_withdraw_tables (PGconn *conn) } PQclear (result); - result = PQexec (conn, + result = PQexec (conn, "CREATE TABLE IF NOT EXISTS refresh_collectable" "(" " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " @@ -245,7 +245,7 @@ main (int argc, char *const *argv) GNUNET_GETOPT_OPTION_END }; - if (GNUNET_GETOPT_run ("taler-mint-serve", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-serve", options, argc, argv) < 0) return 1; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-dbinit", "INFO", NULL)); @@ -256,7 +256,7 @@ main (int argc, char *const *argv) return 1; } - cfg = TALER_MINT_config_load (mint_base_dir); + cfg = TALER_config_load (mint_base_dir); if (NULL == cfg) { fprintf (stderr, "Can't load mint configuration.\n"); @@ -282,4 +282,3 @@ main (int argc, char *const *argv) return 0; } - diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index ffd97a1ad..cde603168 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -233,7 +233,7 @@ mint_serve_process_config (const char *mint_directory) char *master_pub_str; char *db_cfg; - cfg = TALER_MINT_config_load (mint_directory); + cfg = TALER_config_load (mint_directory); if (NULL == cfg) { fprintf (stderr, diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index fcc6d915f..49c359a89 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -117,7 +117,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, /* coin valid but not known => insert into DB */ known_coin.is_refreshed = GNUNET_NO; - known_coin.expended_balance = TALER_amount_ntoh (deposit->amount); + known_coin.expended_balance = deposit->amount; known_coin.public_info = coin_info; if (GNUNET_OK != TALER_MINT_DB_insert_known_coin (db_conn, &known_coin)) @@ -419,8 +419,7 @@ mint_amount_native_zero () struct TALER_Amount amount; memset (&amount, 0, sizeof (amount)); - // FIXME: load from config - memcpy (amount.currency, "EUR", 3); + memcpy (amount.currency, MINT_CURRENCY, strlen (MINT_CURRENCY) + 1); return amount; } diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index ed0eca8bb..ee9f76d5d 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -23,9 +23,8 @@ * @author Christian Grothoff * * TODO: - * - actually verify coin signature - * - revisit `struct Deposit` parsing once the struct - * has been finalized + * - missing 'wire' format check (well-formed SEPA-details) + * - ugliy if-construction for deposit type */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> @@ -59,19 +58,25 @@ verify_and_execute_deposit (struct MHD_Connection *connection, const struct Deposit *deposit) { struct MintKeyState *key_state; + struct TALER_DepositRequest dr; - /* FIXME: verify coin signature! */ - /* - if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_DEPOSIT, - &deposit->purpose, - &deposit->coin_sig, - &deposit->coin_pub)) + dr.purpose.purpose = htonl (TALER_SIGNATURE_DEPOSIT); + dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); + dr.h_contract = deposit->h_contract; + dr.h_wire = deposit->h_wire; + dr.transaction_id = GNUNET_htonll (deposit->transaction_id); + dr.amount = TALER_amount_hton (deposit->amount); + dr.coin_pub = deposit->coin.coin_pub; + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_DEPOSIT, + &dr.purpose, + &deposit->csig, + &deposit->coin.coin_pub)) { - resp = json_pack ("{s:s}", "error", "Signature verfication failed"); + LOG_WARNING ("Invalid signature on /deposit request\n"); return TALER_MINT_reply_arg_invalid (connection, "csig"); } - */ key_state = TALER_MINT_key_state_acquire (); if (GNUNET_YES != @@ -80,10 +85,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, { LOG_WARNING ("Invalid coin passed for /deposit\n"); TALER_MINT_key_state_release (key_state); - return TALER_MINT_reply_json_pack (connection, - MHD_HTTP_NOT_FOUND, - "{s:s}", - "error", "Coin is not valid"); + return TALER_MINT_reply_coin_invalid (connection); } TALER_MINT_key_state_release (key_state); @@ -101,6 +103,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, * @param root root of the posted JSON * @param purpose is this a #TALER_SIGNATURE_DEPOSIT or * #TALER_SIGNATURE_INCREMENTAL_DEPOSIT // FIXME: bad type, use enum! + * @param amount how much should be deposited * @param wire json describing the wire details (?) * @return MHD result code */ @@ -108,6 +111,7 @@ static int parse_and_handle_deposit_request (struct MHD_Connection *connection, const json_t *root, uint32_t purpose, + const struct TALER_Amount *amount, const json_t *wire) { int res; @@ -155,6 +159,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, return TALER_MINT_reply_arg_invalid (connection, "denom_pub"); } + /* FIXME: check that "wire" is formatted correctly */ if (NULL == (wire_enc = json_dumps (wire, JSON_COMPACT | JSON_SORT_KEYS))) { GNUNET_CRYPTO_rsa_public_key_free (deposit.coin.denom_pub); @@ -172,9 +177,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, deposit.wire = wire; deposit.purpose = purpose; - - // FIXME: deposit.amount not initialized! - + deposit.amount = *amount; res = verify_and_execute_deposit (connection, &deposit); GNUNET_CRYPTO_rsa_public_key_free (deposit.coin.denom_pub); @@ -212,6 +215,8 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, const char *deposit_type; int res; uint32_t purpose; + struct TALER_Amount amount; + json_t *f; res = TALER_MINT_parse_post_json (connection, connection_cls, @@ -223,16 +228,35 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, if ( (GNUNET_NO == res) || (NULL == json) ) return MHD_YES; if (-1 == json_unpack (json, - "{s:s, s:o}", + "{s:s, s:o, f:o}", "type", &deposit_type, - "wire", &wire)) + "wire", &wire, + "f", &f)) { GNUNET_break_op (0); + json_decref (json); return TALER_MINT_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, "{s:s}", "error", "Bad format"); } + res = TALER_MINT_parse_amount_json (connection, + f, + &amount); + json_decref (f); + if (GNUNET_SYSERR == res) + { + json_decref (wire); + json_decref (json); + return MHD_NO; + } + if (GNUNET_NO == res) + { + json_decref (wire); + json_decref (json); + return MHD_YES; + } + /* FIXME: use array search and enum, this is ugly */ if (0 == strcmp ("DIRECT_DEPOSIT", deposit_type)) purpose = TALER_SIGNATURE_DEPOSIT; else if (0 == strcmp ("INCREMENTAL_DEPOSIT", deposit_type)) @@ -241,6 +265,7 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, { GNUNET_break_op (0); json_decref (wire); + json_decref (json); return TALER_MINT_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, "{s:s}", @@ -249,8 +274,10 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh, res = parse_and_handle_deposit_request (connection, json, purpose, + &amount, wire); json_decref (wire); + json_decref (json); return res; } diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index c4e28bba7..066f18913 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -110,8 +110,8 @@ buffer_deinit (struct Buffer *buf) * @param data the data to append * @param size the size of @a data * @param max_size maximum size that the buffer can grow to - * @return GNUNET_OK on success, - * GNUNET_NO if the buffer can't accomodate for the new data + * @return #GNUNET_OK on success, + * #GNUNET_NO if the buffer can't accomodate for the new data */ static int buffer_append (struct Buffer *buf, @@ -153,14 +153,14 @@ buffer_append (struct Buffer *buf, * @param upload_data the POST data * @param upload_data_size number of bytes in @a upload_data * @param json the JSON object for a completed request - * @returns - * GNUNET_YES if json object was parsed or at least + * @return + * #GNUNET_YES if json object was parsed or at least * may be parsed in the future (call again); * `*json` will be NULL if we need to be called again, * and non-NULL if we are done. - * GNUNET_NO is request incomplete or invalid + * #GNUNET_NO is request incomplete or invalid * (error message was generated) - * GNUNET_SYSERR on internal error + * #GNUNET_SYSERR on internal error * (we could not even queue an error message, * close HTTP session with MHD_NO) */ @@ -606,6 +606,78 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec) /** + * Parse amount specified in JSON format. + * + * @param connection the MHD connection (to report errors) + * @param f json specification of the amount + * @param amount[OUT] set to the amount specified in @a f + * @return + * #GNUNET_YES if parsing was successful + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error, error response was not generated + */ +int +TALER_MINT_parse_amount_json (struct MHD_Connection *connection, + json_t *f, + struct TALER_Amount *amount) +{ + json_int_t value; + json_int_t fraction; + const char *currency; + struct TALER_Amount a; + + if (-1 == json_unpack (f, + "{s:I, s:I, s:s}", + "value", &value, + "fraction", &fraction, + "currency", ¤cy)) + { + LOG_WARNING ("Failed to parse JSON amount specification\n"); + if (MHD_YES != + TALER_MINT_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s}", + "error", "Bad format")) + return GNUNET_SYSERR; + return GNUNET_NO; + } + if ( (value < 0) || + (fraction < 0) || + (value > UINT32_MAX) || + (fraction > UINT32_MAX) ) + { + LOG_WARNING ("Amount specified not in allowed range\n"); + if (MHD_YES != + TALER_MINT_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s}", + "error", "Amount outside of allowed range")) + return GNUNET_SYSERR; + return GNUNET_NO; + } + if (0 != strcmp (currency, + MINT_CURRENCY)) + { + LOG_WARNING ("Currency specified not supported by this mint\n"); + if (MHD_YES != + TALER_MINT_reply_json_pack (connection, + MHD_HTTP_BAD_REQUEST, + "{s:s, s:s}", + "error", "Currency not supported", + "currency", currency)) + return GNUNET_SYSERR; + return GNUNET_NO; + } + a.value = (uint32_t) value; + a.fraction = (uint32_t) fraction; + GNUNET_assert (strlen (MINT_CURRENCY) < TALER_CURRENCY_LEN); + strcpy (a.currency, MINT_CURRENCY); + *amount = TALER_amount_normalize (a); + return GNUNET_OK; +} + + +/** * Extract base32crockford encoded data from request. * * Queues an error response to the connection if the parameter is missing or diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h index 9c4d8aafe..1c13c9469 100644 --- a/src/mint/taler-mint-httpd_parsing.h +++ b/src/mint/taler-mint-httpd_parsing.h @@ -25,6 +25,7 @@ #include <microhttpd.h> #include <jansson.h> +#include "taler_util.h" /** @@ -216,6 +217,23 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec); /** + * Parse amount specified in JSON format. + * + * @param connection the MHD connection (to report errors) + * @param f json specification of the amount + * @param amount[OUT] set to the amount specified in @a f + * @return + * #GNUNET_YES if parsing was successful + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error, error response was not generated + */ +int +TALER_MINT_parse_amount_json (struct MHD_Connection *connection, + json_t *f, + struct TALER_Amount *amount); + + +/** * Extraxt fixed-size base32crockford encoded data from request. * * Queues an error response to the connection if the parameter is missing or diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 12d4bced7..432772d79 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -125,6 +125,26 @@ TALER_MINT_reply_arg_invalid (struct MHD_Connection *connection, /** + * Send a response indicating an invalid coin. (I.e. the signature + * over the public key of the coin does not match a valid signing key + * of this mint). + * + * @param connection the MHD connection to use + * @return MHD result code + */ +int +TALER_MINT_reply_coin_invalid (struct MHD_Connection *connection) +{ + /* TODO: may want to be more precise in the future and + distinguish bogus signatures from bogus public keys. */ + return TALER_MINT_reply_json_pack (connection, + MHD_HTTP_NOT_FOUND, + "{s:s}", + "error", "Coin is not valid"); +} + + +/** * Send a response indicating a missing argument. * * @param connection the MHD connection to use diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 51abd9fb4..471d73bd1 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -78,6 +78,18 @@ TALER_MINT_reply_arg_invalid (struct MHD_Connection *connection, /** + * Send a response indicating an invalid coin. (I.e. the signature + * over the public key of the coin does not match a valid signing key + * of this mint). + * + * @param connection the MHD connection to use + * @return MHD result code + */ +int +TALER_MINT_reply_coin_invalid (struct MHD_Connection *connection); + + +/** * Send a response indicating a missing argument. * * @param connection the MHD connection to use diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c index 419baf501..09f59ab2f 100644 --- a/src/mint/taler-mint-keycheck.c +++ b/src/mint/taler-mint-keycheck.c @@ -162,7 +162,7 @@ main (int argc, char *const *argv) return 1; } - kcfg = TALER_MINT_config_load (mintdir); + kcfg = TALER_config_load (mintdir); if (NULL == kcfg) { fprintf (stderr, "can't load mint configuration\n"); @@ -172,4 +172,3 @@ main (int argc, char *const *argv) return 1; return 0; } - diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 7c35317ce..f8670eb97 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -621,7 +621,7 @@ main (int argc, char *const *argv) } ROUND_TO_SECS (now, abs_value_us); - kcfg = TALER_MINT_config_load (mintdir); + kcfg = TALER_config_load (mintdir); if (NULL == kcfg) { fprintf (stderr, "can't load mint configuration\n"); diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index 3dd94f84b..48a9c88b4 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -38,7 +38,7 @@ static PGconn *db_conn; /** * Create a new or add to existing reserve. * Fails if currencies do not match. - * + * * @param denom denomination to add * * @return ... @@ -72,7 +72,7 @@ reservemod_add (struct TALER_Amount denom) reserve_pub, &value, &fraction, - denom.currency, + denom.currency, &exnbo}; int param_lengths[] = {32, 4, 4, strlen(denom.currency), 8}; int param_formats[] = {1, 1, 1, 1, 1}; @@ -81,14 +81,14 @@ reservemod_add (struct TALER_Amount denom) " expiration_date )" "values ($1,$2,$3,$4,$5);", 5, NULL, (const char **) param_values, param_lengths, param_formats, 1); - + if (PGRES_COMMAND_OK != PQresultStatus (result)) { fprintf (stderr, "Insert failed: %s\n", PQresultErrorMessage (result)); return GNUNET_SYSERR; } - } - else + } + else { struct TALER_Amount old_denom; struct TALER_Amount new_denom; @@ -125,8 +125,8 @@ reservemod_add (struct TALER_Amount denom) return GNUNET_SYSERR; } - } - return GNUNET_OK; + } + return GNUNET_OK; } @@ -159,18 +159,18 @@ main (int argc, char *const *argv) GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keycheck", "WARNING", NULL)); - if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0) return 1; if (NULL == mintdir) { - fprintf (stderr, "mint directory not given\n"); + fprintf (stderr, "mint directory not given\n"); return 1; } reserve_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey); if ((NULL == reserve_pub_str) || (GNUNET_OK != GNUNET_STRINGS_string_to_data (reserve_pub_str, - strlen (reserve_pub_str), + strlen (reserve_pub_str), reserve_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))) { @@ -178,7 +178,7 @@ main (int argc, char *const *argv) return 1; } - kcfg = TALER_MINT_config_load (mintdir); + kcfg = TALER_config_load (mintdir); if (NULL == kcfg) { fprintf (stderr, "can't load mint configuration\n"); @@ -212,4 +212,3 @@ main (int argc, char *const *argv) } return 0; } - diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c index 776bc15d2..00664cbbf 100644 --- a/src/mint/test_mint_deposits.c +++ b/src/mint/test_mint_deposits.c @@ -104,9 +104,12 @@ run (void *cls, char *const *args, const char *cfgfile, htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); deposit->amount.fraction = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); - strcpy (deposit->amount.currency, "EUR"); + GNUNET_assert (strlen (MINT_CURRENCY) < sizeof (deposit->amount.currency)); + strcpy (deposit->amount.currency, MINT_CURRENCY); /* Copy wireformat */ - (void) memcpy (deposit->wire, wire, sizeof (wire)); + memcpy (deposit->wire, + wire, + sizeof (wire)); EXITIF (GNUNET_OK != TALER_MINT_DB_insert_deposit (conn, deposit)); EXITIF (GNUNET_OK != TALER_MINT_DB_get_deposit (conn, diff --git a/src/util/util.c b/src/util/util.c index 440b49fab..de085d088 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -16,7 +16,7 @@ /** * @file util.c - * @brief Common utility functions + * @brief Common utility functions; we might choose to move those to GNUnet at some point * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Florian Dold * @author Benedikt Mueller @@ -60,4 +60,33 @@ TALER_data_to_string_alloc (const void *buf, size_t size) } +/** + * Load configuration by parsing all configuration + * files in the given directory. + * + * @param base_dir directory with the configuration files + * @return NULL on error, otherwise configuration + */ +struct GNUNET_CONFIGURATION_Handle * +TALER_config_load (const char *base_dir) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + char *cfg_dir; + int res; + + res = GNUNET_asprintf (&cfg_dir, + "%s" DIR_SEPARATOR_STR "config", + base_dir); + GNUNET_assert (res > 0); + cfg = GNUNET_CONFIGURATION_create (); + res = GNUNET_CONFIGURATION_load_from (cfg, cfg_dir); + GNUNET_free (cfg_dir); + if (GNUNET_OK != res) + return NULL; + return cfg; +} + + + + /* end of util.c */ |