mention need to audit randomness of gamma

This commit is contained in:
Christian Grothoff 2015-09-27 20:32:30 +02:00
commit bf8b9d1435
2159 changed files with 115320 additions and 1535 deletions

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ GTAGS
src/lib/test_mint_api
doc/doxygen/doxygen_sqlite3.db
src/mint-lib/test_mint_api
src/mint-tools/taler-auditor-sign
src/mint-tools/taler-mint-dbinit
src/mint-tools/taler-mint-keycheck
src/mint-tools/taler-mint-keyup

View File

@ -2,7 +2,8 @@
# Currency supported by the mint (can only be one)
CURRENCY = EUR
# Wire format supproted by the mint (currently only SEPA is implemented)
# Wire format supported by the mint, case-insensitive.
# Examples for formats include 'test' for testing and 'sepa' (for EU IBAN).
WIREFORMAT = SEPA
# HTTP port the mint listens to
@ -19,3 +20,9 @@ TESTRUN = YES
[mintdb-postgres]
DB_CONN_STR = "postgres:///talercheck"
[mint-wire-sepa]
SEPA_RESPONSE_FILE = "sepa.json"
[mint-wire-test]
REDIRECT_URL = "http://test/"

View File

@ -3,12 +3,13 @@
SUBDIRS = . doxygen
man_MANS = \
taler-auditor-sign.1 \
taler-mint-dbinit.1 \
taler-mint-httpd.1 \
taler-mint-keyup.1 \
taler-mint-keycheck.1 \
taler-mint-reservemod.1 \
taler.conf.5
taler.conf.5
EXTRA_DIST = \
coding-style.txt \

98714
doc/paper/rfc.bib Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,13 @@
year={2008}
}
@InProceedings{apod,
author = {Elli Androulaki and Steven Bellovin},
title = {APOD: Anonymous Physical Object Delivery},
booktitle = {Symposium on Privacy-Enhancing Technologies (PETS)},
year = {2009},
}
@Article{blum1981,
author = {Manuel Blum},
title = {Coin Flipping by Telephone},
@ -12,6 +19,64 @@
pages = {11-15},
}
@Misc{greece2015cash,
author = {Reuters},
title = {Greek council recommends 60 euro limit on ATM withdrawals from Tuesday},
howpublished = {\url{http://www.reuters.com/article/2015/06/28/eurozone-greece-limits-idUSA8N0Z302P20150628}},
month = {June},
year = {2015},
}
@Misc{france2015cash,
author = {Heinz-Peter Bader},
title = {France steps up monitoring of cash payments to fight low-cost terrorism},
howpublished = {\url{http://www.reuters.com/article/2015/03/18/us-france-security-financing-idUSKBN0ME14720150318}},
month = {Mar},
year = {2015},
}
@Misc{fatf1997,
title = {FATF-IX report on money laundering typologies},
howpublished = {\url{http://www.fatf-gafi.org/media/fatf/documents/reports/1996\%201997\%20ENG.pdf}},
month = {feb},
year = {1998},
}
@TechReport{,
author = {},
title = {},
institution = {},
year = {},
OPTkey = {},
OPTtype = {},
OPTnumber = {},
OPTaddress = {},
OPTmonth = {},
OPTnote = {},
OPTannote = {}
}
@InProceedings{sander1999escrow,
author = {Tomas Sander and Amnon Ta-Shma},
title = {On Anonymous Electronic Cash and Crime},
booktitle = {ISW'99},
year = {1999},
series = {LNCS 1729},
pages = {202--206},
}
@Article{solms1992perfect,
author = {Sebastiaan H. von Solms and David Naccache},
title = {On blind signatures and perfect crimes},
journal = {Computers \& Security},
year = {1992},
volume = {11},
number = {6},
pages = {581--583},
}
@inproceedings{chaum1990untraceable,
title={Untraceable electronic cash},
author={Chaum, David and Fiat, Amos and Naor, Moni},
@ -48,6 +113,23 @@
organization={IEEE}
}
@InProceedings{fc2014murdoch,
author = {Stephen Murdoch and Ross Anderson},
title = {Security Protocols and Evidence: Where Many Payment Systems Fail},
booktitle = {Financial Cryptography and Data Security},
year = {2014},
}
@book{ engels1844,
author = "Friedrich Engels",
title = "{Umrisse zu einer Kritik der National\"okonomie}",
year = "1844",
publisher = "Ruge and Marx, Paris",
}
@inproceedings{selby2004analyzing,
title={Analyzing the Success and Failure of Recent e-Payment Schemes},
author={Selby, Jack R},
@ -91,4 +173,3 @@
www_pdf_url = {https://www.torproject.org/svn/trunk/doc/design-paper/tor-design.pdf},
www_section = {Anonymous communication},
}

File diff suppressed because it is too large Load Diff

35
doc/taler-auditor-sign.1 Normal file
View File

@ -0,0 +1,35 @@
.TH TALER\-AUDITOR\-SIGN 1 "Sep 15, 2015" "GNU Taler"
.SH NAME
taler\-auditor\-sign \- Sign mint denomination as auditor.
.SH SYNOPSIS
.B taler\-auditor\-sign
.RI [ options ]
.br
.SH DESCRIPTION
\fBtaler\-auditor\-sign\fP is a command line tool to be used by an auditor to sign that he is aware of certain keys being used by a mint. Using this signature, the auditor affirms that he will verify that the mint is properly accounting for those coins.
.SH OPTIONS
.B
.IP "\-a FILE, \-\-auditor-key=FILE"
Location of the private EdDSA auditor key. If it does not exist, it will be created.
.B
.IP "\-h, \-\-help"
Print short help on options.
.B
.IP "\-m KEY, \-\-mint-key=KEY"
Public key of the mint in Crockford base32 encoding, for example as generated by gnunet\-ecc \-p.
.B
.IP "\-r FILE, \-\-mint-request=FILE"
File with the mint's denomination key signing request as generated by taler\-mint\-keyup \-o.
.B
.IP "\-o FILE, \-\-output=FILE"
File where the auditor should write the EdDSA signature.
.SH BUGS
Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <taler@gnu.org>
.SH "SEE ALSO"
\fBtaler\-mint\-keyup\fP(1), \fBgnunet\-ecc\fP(1), \fBtaler.conf\fP(5)

View File

@ -13,6 +13,9 @@ taler\-mint\-httpd \- Run Taler mint (with RESTful API)
.SH OPTIONS
.B
.IP "\-C, \-\-connection-close"
Force each HTTP connection to be closed after each request (useful in combination with \-f to avoid having to wait for nc to time out).
.B
.IP "\-d DIRNAME, \-\-mint-dir=DIRNAME"
Use the configuration and other resources for the mint to operate from DIRNAME.
.B

View File

@ -22,6 +22,9 @@ Print short help on options.
.IP "\-m FILE, \-\-master-key=FILE"
Location of the private EdDSA offline master key of the mint.
.B
.IP "\-o FILE, \-\-ouptut=FILE"
Where to write a denomination key signing request file to be given to the auditor.
.B
.IP "\-t TIMESTAMP, \-\-time=TIMESTAMP"
Operate as if the current time was TIMESTAMP.
.B

View File

@ -189,6 +189,18 @@ struct TALER_AuditorPublicKeyP
};
/**
* @brief Type of the public key used by the auditor.
*/
struct TALER_AuditorSignatureP
{
/**
* Taler uses EdDSA signatures for auditors.
*/
struct GNUNET_CRYPTO_EddsaSignature eddsa_sig;
};
/**
* @brief Type of the offline master public keys used by the mint.
*/

View File

@ -167,12 +167,12 @@ TALER_hash_json (json_t *json,
/**
* Check if the given wire format JSON object is correctly formatted
*
* @param type the type of the wire format
* @param allowed NULL-terminated array of allowed wire format types
* @param wire the JSON wire format object
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
*/
int
TALER_json_validate_wireformat (const char *type,
TALER_json_validate_wireformat (const char **allowed,
const json_t *wire);

View File

@ -149,6 +149,11 @@ struct TALER_MINT_DenomPublicKey
*/
struct TALER_DenominationPublicKey key;
/**
* The hash of the public key.
*/
struct GNUNET_HashCode h_key;
/**
* Timestamp indicating when the denomination key becomes valid
*/
@ -165,6 +170,15 @@ struct TALER_MINT_DenomPublicKey
*/
struct GNUNET_TIME_Absolute deposit_valid_until;
/**
* When do signatures with this denomination key become invalid?
* After this point, these signatures cannot be used in (legal)
* disputes anymore, as the Mint is then allowed to destroy its side
* of the evidence. @e expire_legal is expected to be significantly
* larger than @e expire_spend (by a year or more).
*/
struct GNUNET_TIME_Absolute expire_legal;
/**
* The value of this denomination
*/
@ -204,6 +218,8 @@ struct TALER_MINT_AuditorInformation
* that website. We expect that in practice software is going to
* often ship with an initial list of accepted auditors, just like
* browsers ship with a CA root store.
*
* This field may be NULL. (#3987).
*/
const char *auditor_url;
@ -218,7 +234,7 @@ struct TALER_MINT_AuditorInformation
* elements point to the same locations as the entries
* in the key's main `denom_keys` array.
*/
struct TALER_MINT_DenomPublicKey *const*denom_keys;
const struct TALER_MINT_DenomPublicKey **denom_keys;
};
@ -246,7 +262,7 @@ struct TALER_MINT_Keys
/**
* Array of the keys of the auditors of the mint.
*/
struct TALER_AuditorPublicKeyP *auditors;
struct TALER_MINT_AuditorInformation *auditors;
/**
* Length of the @e sign_keys array.
@ -353,6 +369,100 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
const struct TALER_DenominationPublicKey *pk);
/**
* Obtain the denomination key details from the mint.
*
* @param keys the mint's key set
* @param hc hash of the public key of the denomination to lookup
* @return details about the given denomination key
*/
const struct TALER_MINT_DenomPublicKey *
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
const struct GNUNET_HashCode *hc);
/* ********************* /wire *********************** */
/**
* @brief A Wire format inquiry handle
*/
struct TALER_MINT_WireHandle;
/**
* Callbacks of this type are used to serve the result of submitting a
* wire format inquiry request to a mint.
*
* The callback is invoked multiple times, once for each supported @a
* method. Finally, it is invoked one more time with cls/0/NULL/NULL
* to indicate the end of the iteration. If any request fails to
* generate a valid response from the mint, @a http_status will also
* be zero and the iteration will also end. Thus, the iteration
* always ends with a final call with an @a http_status of 0. If the
* @a http_status is already 0 on the first call, then the response to
* the /wire request was invalid. Later, clients can tell the
* difference between @a http_status of 0 indicating a failed
* /wire/method request and a regular end of the iteration by @a
* method being non-NULL. If the mint simply correctly asserts that
* it does not support any methods, @a method will be NULL but the @a
* http_status will be #MHD_HTTP_OK for the first call (followed by a
* cls/0/NULL/NULL call to signal the end of the iteration).
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
* 0 if the mint's reply is bogus (fails to follow the protocol)
* @param method wire format method supported, i.e. "test" or "sepa", or NULL
* if already the /wire request failed.
* @param obj the received JSON reply, if successful this should be the wire
* format details as provided by /wire/METHOD/, or NULL if the
* reply was not in JSON format (in this case, the client might
* want to do an HTTP request to /wire/METHOD/ with a browser to
* provide more information to the user about the @a method).
*/
typedef void
(*TALER_MINT_WireResultCallback) (void *cls,
unsigned int http_status,
const char *method,
json_t *obj);
/**
* Obtain information about a mint's wire instructions.
* A mint may provide wire instructions for creating
* a reserve. The wire instructions also indicate
* which wire formats merchants may use with the mint.
* This API is typically used by a wallet for wiring
* funds, and possibly by a merchant to determine
* supported wire formats.
*
* Note that while we return the (main) response verbatim to the
* caller for further processing, we do already verify that the
* response is well-formed (i.e. that signatures included in the
* response are all valid). If the mint's reply is not well-formed,
* we return an HTTP status code of zero to @a cb.
*
* @param mint the mint handle; the mint must be ready to operate
* @param wire_cb the callback to call when a reply for this request is available
* @param wire_cb_cls closure for the above callback
* @return a handle for this request
*/
struct TALER_MINT_WireHandle *
TALER_MINT_wire (struct TALER_MINT_Handle *mint,
TALER_MINT_WireResultCallback wire_cb,
void *wire_cb_cls);
/**
* Cancel a wire information request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param wh the wire information request handle
*/
void
TALER_MINT_wire_cancel (struct TALER_MINT_WireHandle *wh);
/* ********************* /deposit *********************** */
@ -437,13 +547,13 @@ void
TALER_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit);
/* ********************* /withdraw/status *********************** */
/* ********************* /reserve/status *********************** */
/**
* @brief A /withdraw/status Handle
* @brief A /reserve/status Handle
*/
struct TALER_MINT_WithdrawStatusHandle;
struct TALER_MINT_ReserveStatusHandle;
/**
@ -513,12 +623,12 @@ struct TALER_MINT_ReserveHistory
* @param history detailed transaction history, NULL on error
*/
typedef void
(*TALER_MINT_WithdrawStatusResultCallback) (void *cls,
unsigned int http_status,
json_t *json,
const struct TALER_Amount *balance,
unsigned int history_length,
const struct TALER_MINT_ReserveHistory *history);
(*TALER_MINT_ReserveStatusResultCallback) (void *cls,
unsigned int http_status,
json_t *json,
const struct TALER_Amount *balance,
unsigned int history_length,
const struct TALER_MINT_ReserveHistory *history);
/**
@ -537,11 +647,11 @@ typedef void
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawStatusHandle *
TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_MINT_WithdrawStatusResultCallback cb,
void *cb_cls);
struct TALER_MINT_ReserveStatusHandle *
TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_MINT_ReserveStatusResultCallback cb,
void *cb_cls);
/**
@ -551,16 +661,16 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
* @param wsh the withdraw status request handle
*/
void
TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh);
TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh);
/* ********************* /withdraw/sign *********************** */
/* ********************* /reserve/withdraw *********************** */
/**
* @brief A /withdraw/sign Handle
* @brief A /reserve/withdraw Handle
*/
struct TALER_MINT_WithdrawSignHandle;
struct TALER_MINT_ReserveWithdrawHandle;
/**
@ -574,14 +684,14 @@ struct TALER_MINT_WithdrawSignHandle;
* @param full_response full response from the mint (for logging, in case of errors)
*/
typedef void
(*TALER_MINT_WithdrawSignResultCallback) (void *cls,
unsigned int http_status,
const struct TALER_DenominationSignature *sig,
json_t *full_response);
(*TALER_MINT_ReserveWithdrawResultCallback) (void *cls,
unsigned int http_status,
const struct TALER_DenominationSignature *sig,
json_t *full_response);
/**
* Withdraw a coin from the mint using a /withdraw/sign request. This
* Withdraw a coin from the mint using a /reserve/withdraw request. This
* API is typically used by a wallet. Note that to ensure that no
* money is lost in case of hardware failures, the caller must have
* committed (most of) the arguments to disk before calling, and be
@ -601,14 +711,14 @@ typedef void
* if the inputs are invalid (i.e. denomination key not with this mint).
* In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawSignHandle *
TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
const struct TALER_MINT_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_MINT_WithdrawSignResultCallback res_cb,
void *res_cb_cls);
struct TALER_MINT_ReserveWithdrawHandle *
TALER_MINT_reserve_withdraw (struct TALER_MINT_Handle *mint,
const struct TALER_MINT_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_MINT_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls);
/**
@ -618,7 +728,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
* @param sign the withdraw sign request handle
*/
void
TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign);
TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign);
/* ********************* /refresh/melt+reveal ***************************** */

View File

@ -37,6 +37,12 @@
*/
#define TALER_MINTDB_DIR_DENOMINATION_KEYS "denomkeys"
/**
* Subdirectory under the mint's base directory which contains
* the mint's auditing information.
*/
#define TALER_MINTDB_DIR_AUDITORS "auditors"
GNUNET_NETWORK_STRUCT_BEGIN
@ -62,7 +68,7 @@ struct TALER_MINTDB_PrivateSigningKeyInformationP
/**
* Information about a denomination key.
*/
*/
struct TALER_MINTDB_DenominationKeyInformationP
{
@ -123,23 +129,6 @@ typedef int
const struct TALER_MINTDB_PrivateSigningKeyInformationP *ski);
/**
* @brief Iterator over denomination keys.
*
* @param cls closure
* @param dki the denomination key
* @param alias coin alias
* @return #GNUNET_OK to continue to iterate,
* #GNUNET_NO to stop iteration with no error,
* #GNUNET_SYSERR to abort iteration with error!
*/
typedef int
(*TALER_MINTDB_DenominationKeyIterator)(void *cls,
const char *alias,
const struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
/**
* Call @a it for each signing key found in the @a mint_base_dir.
*
@ -158,6 +147,23 @@ TALER_MINTDB_signing_keys_iterate (const char *mint_base_dir,
void *it_cls);
/**
* @brief Iterator over denomination keys.
*
* @param cls closure
* @param dki the denomination key
* @param alias coin alias
* @return #GNUNET_OK to continue to iterate,
* #GNUNET_NO to stop iteration with no error,
* #GNUNET_SYSERR to abort iteration with error!
*/
typedef int
(*TALER_MINTDB_DenominationKeyIterator)(void *cls,
const char *alias,
const struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
/**
* Call @a it for each denomination key found in the @a mint_base_dir.
*
@ -201,6 +207,67 @@ TALER_MINTDB_denomination_key_read (const char *filename,
struct TALER_MINTDB_DenominationKeyIssueInformation *dki);
/**
* @brief Iterator over auditor information.
*
* @param cls closure
* @param apub the auditor's public key
* @param mpub the mint's public key (as expected by the auditor)
* @param dki_len length of @a asig and @a dki arrays
* @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len
* @param dki array of denomination coin data signed by the auditor, of length @a dki_len
* @return #GNUNET_OK to continue to iterate,
* #GNUNET_NO to stop iteration with no error,
* #GNUNET_SYSERR to abort iteration with error!
*/
typedef int
(*TALER_MINTDB_AuditorIterator)(void *cls,
const struct TALER_AuditorPublicKeyP *apub,
const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len,
const struct TALER_AuditorSignatureP *asigs,
const struct TALER_DenominationKeyValidityPS *dki);
/**
* Call @a it with information for each auditor found in the @a mint_base_dir.
*
* @param mint_base_dir base directory for the mint,
* the signing keys must be in the #TALER_MINTDB_DIR_DENOMINATION_KEYS
* subdirectory
* @param it function to call with auditor information
* @param it_cls closure for @a it
* @return -1 on error, 0 if no files were found, otherwise
* a positive number (however, even with a positive
* number it is possible that @a it was never called
* as maybe none of the files were well-formed)
*/
int
TALER_MINTDB_auditor_iterate (const char *mint_base_dir,
TALER_MINTDB_AuditorIterator it,
void *it_cls);
/**
* Write auditor information to the given file.
*
* @param filename the file where to write the auditor information to
* @param apub the auditor's public key
* @param asigs the auditor's signatures, array of length @a dki_len
* @param mpub the mint's public key (as expected by the auditor)
* @param dki_len length of @a dki and @a asigs arrays
* @param dki array of denomination coin data signed by the auditor
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
*/
int
TALER_MINTDB_auditor_write (const char *filename,
const struct TALER_AuditorPublicKeyP *apub,
const struct TALER_AuditorSignatureP *asigs,
const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len,
const struct TALER_DenominationKeyValidityPS *dki);
/**
* Initialize the plugin.
*

View File

@ -416,30 +416,6 @@ struct TALER_MINTDB_LinkDataList
};
/**
* @brief Specification for a /lock operation.
*/
struct TALER_MINTDB_LockOperation
{
/**
* Information about the coin that is being locked.
*/
struct TALER_CoinPublicInfo coin;
/**
* Signature over the locking operation.
*/
struct TALER_CoinSpendSignatureP coin_sig;
/**
* How much value is being locked?
*/
struct TALER_Amount amount;
// FIXME: more needed...
};
/**
* @brief Enumeration to classify the different types of transactions
* that can be done with a coin.
@ -454,12 +430,8 @@ enum TALER_MINTDB_TransactionType
/**
* /refresh/melt operation.
*/
TALER_MINTDB_TT_REFRESH_MELT = 1,
TALER_MINTDB_TT_REFRESH_MELT = 1
/**
* /lock operation.
*/
TALER_MINTDB_TT_LOCK = 2
};
@ -495,11 +467,6 @@ struct TALER_MINTDB_TransactionList
*/
struct TALER_MINTDB_RefreshMelt *melt;
/**
* Details if transaction was a /lock operation.
*/
struct TALER_MINTDB_LockOperation *lock;
} details;
};
@ -549,6 +516,31 @@ struct TALER_MINTDB_MeltCommitment
struct TALER_MINTDB_Session;
/**
* Function called with details about deposits that
* have been made, with the goal of executing the
* corresponding wire transaction.
*
* @param cls closure
* @param id transaction ID (used as future `min_id` to avoid
* iterating over transactions more than once)
* @param amount_with_fee amount that was deposited including fee
* @param deposit_fee amount the mint gets to keep as transaction fees
* @param transaction_id unique transaction ID chosen by the merchant
* @param h_contract hash of the contract between merchant and customer
* @param wire wire details for the merchant
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
typedef int
(*TALER_MINTDB_DepositIterator)(void *cls,
uint64_t id,
const struct TALER_Amount *amount_with_fee,
const struct TALER_Amount *deposit_fee,
uint64_t transaction_id,
const struct GNUNET_HashCode *h_contract,
const json_t *wire);
/**
* Function called with the session hashes and transfer secret
* information for a given coin.
@ -636,23 +628,24 @@ struct TALER_MINTDB_Plugin
* Commit a transaction.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to use
* @return #GNUNET_OK on success
* @param session connection to use
* @return #GNUNET_OK on success, #GNUNET_NO if the transaction
* can be retried, #GNUNET_SYSERR on hard failures
*/
int
(*commit) (void *cls,
struct TALER_MINTDB_Session *sesssion);
struct TALER_MINTDB_Session *session);
/**
* Abort/rollback a transaction.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to use
* @param session connection to use
*/
void
(*rollback) (void *cls,
struct TALER_MINTDB_Session *sesssion);
struct TALER_MINTDB_Session *session);
/**
@ -661,7 +654,7 @@ struct TALER_MINTDB_Plugin
* with this key have.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to use
* @param session connection to use
* @param denom_pub the public key used for signing coins of this denomination
* @param issue issuing information with value, fees and other info about the coin
* @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
@ -677,7 +670,7 @@ struct TALER_MINTDB_Plugin
* Fetch information about a denomination key.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to use
* @param session connection to use
* @param denom_pub the public key used for signing coins of this denomination
* @param[out] issue set to issue information with value, fees and other info about the coin, can be NULL
* @return #GNUNET_OK on success; #GNUNET_NO if no record was found, #GNUNET_SYSERR on failure
@ -736,7 +729,7 @@ struct TALER_MINTDB_Plugin
* key of the hash of the blinded message.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param h_blind hash of the blinded coin to be signed (will match
* `h_coin_envelope` in the @a collectable to be returned)
* @param collectable corresponding collectable coin (blind signature)
@ -747,7 +740,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_withdraw_info) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *h_blind,
struct TALER_MINTDB_CollectableBlindcoin *collectable);
@ -757,7 +750,7 @@ struct TALER_MINTDB_Plugin
* hash of the blinded message.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param collectable corresponding collectable coin (blind signature)
* if a coin is found
* @return #GNUNET_SYSERR on internal error
@ -766,7 +759,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_withdraw_info) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_MINTDB_CollectableBlindcoin *collectable);
@ -775,13 +768,13 @@ struct TALER_MINTDB_Plugin
* reserve.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to use
* @param session connection to use
* @param reserve_pub public key of the reserve
* @return known transaction history (NULL if reserve is unknown)
*/
struct TALER_MINTDB_ReserveHistory *
(*get_reserve_history) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_ReservePublicKeyP *reserve_pub);
@ -800,7 +793,7 @@ struct TALER_MINTDB_Plugin
* Check if we have the specified deposit already in the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param deposit deposit to search for
* @return #GNUNET_YES if we know this operation,
* #GNUNET_NO if this exact deposit is unknown to us,
@ -808,30 +801,53 @@ struct TALER_MINTDB_Plugin
*/
int
(*have_deposit) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_MINTDB_Deposit *deposit);
/**
* Insert information about deposited coin into the
* database.
* Insert information about deposited coin into the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion connection to the database
* @param session connection to the database
* @param deposit deposit information to store
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
(*insert_deposit) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_MINTDB_Deposit *deposit);
/**
* Obtain information about deposits. Iterates over all deposits
* above a certain ID. Use a @a min_id of 0 to start at the beginning.
* This operation is executed in its own transaction in transaction
* mode "REPEATABLE READ", i.e. we should only see valid deposits.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param session connection to the database
* @param min_id deposit to start at
* @param limit maximum number of transactions to fetch
* @param deposit_cb function to call for each deposit
* @param deposit_cb_cls closure for @a deposit_cb
* @return number of rows processed, 0 if none exist,
* #GNUNET_SYSERR on error
*/
int
(*iterate_deposits) (void *cls,
struct TALER_MINTDB_Session *session,
uint64_t min_id,
uint32_t limit,
TALER_MINTDB_DepositIterator deposit_cb,
void *deposit_cb_cls);
/**
* Lookup refresh session data under the given @a session_hash.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database handle to use
* @param session database handle to use
* @param session_hash hash over the melt to use for the lookup
* @param[out] refresh_session where to store the result
* @return #GNUNET_YES on success,
@ -840,7 +856,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_refresh_session) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
struct TALER_MINTDB_RefreshSession *refresh_session);
@ -849,7 +865,7 @@ struct TALER_MINTDB_Plugin
* Store new refresh session data under the given @a session_hash.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database handle to use
* @param session database handle to use
* @param session_hash hash over the melt to use to locate the session
* @param refresh_session session data to store
* @return #GNUNET_YES on success,
@ -857,7 +873,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*create_refresh_session) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
const struct TALER_MINTDB_RefreshSession *refresh_session);
@ -866,7 +882,7 @@ struct TALER_MINTDB_Plugin
* Store the given /refresh/melt request in the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param oldcoin_index index of the coin to store
* @param melt coin melt operation details to store; includes
* the session hash of the melt
@ -875,7 +891,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_refresh_melt) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
uint16_t oldcoin_index,
const struct TALER_MINTDB_RefreshMelt *melt);
@ -884,7 +900,7 @@ struct TALER_MINTDB_Plugin
* Get information about melted coin details from the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param session_hash hash to identify refresh session
* @param oldcoin_index index of the coin to retrieve
* @param melt melt data to fill in, can be NULL
@ -893,7 +909,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_refresh_melt) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t oldcoin_index,
struct TALER_MINTDB_RefreshMelt *melt);
@ -904,7 +920,7 @@ struct TALER_MINTDB_Plugin
* in a given refresh operation.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param session_hash hash to identify refresh session
* @param num_newcoins number of coins to generate, size of the @a denom_pubs array
* @param denom_pubs array denominations of the coins to create
@ -913,7 +929,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_refresh_order) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t num_newcoins,
const struct TALER_DenominationPublicKey *denom_pubs);
@ -924,7 +940,7 @@ struct TALER_MINTDB_Plugin
* create in the given refresh operation.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param session_hash hash to identify refresh session
* @param num_newcoins size of the @a denom_pubs array
* @param[out] denom_pubs where to write @a num_newcoins denomination keys
@ -933,7 +949,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_refresh_order) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t num_newcoins,
struct TALER_DenominationPublicKey *denom_pubs);
@ -944,7 +960,7 @@ struct TALER_MINTDB_Plugin
* for the given refresh session in the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA
* @param num_newcoins coin index size of the @a commit_coins array
@ -954,7 +970,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_refresh_commit_coins) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_newcoins,
@ -966,7 +982,7 @@ struct TALER_MINTDB_Plugin
* given coin of the given refresh session from the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose set index (1st dimension)
* @param num_coins size of the @a commit_coins array
@ -977,7 +993,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_refresh_commit_coins) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_coins,
@ -989,7 +1005,7 @@ struct TALER_MINTDB_Plugin
* for the given refresh session.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA
* @param num_links size of the @a commit_link array
@ -998,7 +1014,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_refresh_commit_links) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
@ -1009,7 +1025,7 @@ struct TALER_MINTDB_Plugin
* for the given refresh session.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a links array to return
@ -1020,7 +1036,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_refresh_commit_links) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
@ -1031,14 +1047,14 @@ struct TALER_MINTDB_Plugin
* Get all of the information from the given melt commit operation.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection to use
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @return NULL if the @a session_hash does not correspond to any known melt
* operation
*/
struct TALER_MINTDB_MeltCommitment *
(*get_melt_commitment) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash);
@ -1060,7 +1076,7 @@ struct TALER_MINTDB_Plugin
* be used to try to obtain the private keys during "/refresh/link".
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param session_hash hash to identify refresh session
* @param newcoin_index coin index
* @param ev_sig coin signature
@ -1068,7 +1084,7 @@ struct TALER_MINTDB_Plugin
*/
int
(*insert_refresh_out) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t newcoin_index,
const struct TALER_DenominationSignature *ev_sig);
@ -1079,13 +1095,13 @@ struct TALER_MINTDB_Plugin
* information, the denomination keys and the signatures.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param session_hash session to get linkage data for
* @return all known link data for the session
*/
struct TALER_MINTDB_LinkDataList *
(*get_link_data_list) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct GNUNET_HashCode *session_hash);
@ -1108,7 +1124,7 @@ struct TALER_MINTDB_Plugin
*
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param coin_pub public key of the coin
* @param tdc function to call for each session the coin was melted into
* @param tdc_cls closure for @a tdc
@ -1118,56 +1134,24 @@ struct TALER_MINTDB_Plugin
*/
int
(*get_transfer) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
TALER_MINTDB_TransferDataCallback tdc,
void *tdc_cls);
/**
* Test if the given /lock request is known to us.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param lock lock operation
* @return #GNUNET_YES if known,
* #GNUNET_NO if not,
* #GNUNET_SYSERR on internal error
*/
int
(*have_lock) (void *cls,
struct TALER_MINTDB_Session *sesssion,
const struct TALER_MINTDB_LockOperation *lock);
/**
* Store the given /lock request in the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param lock lock operation
* @return #GNUNET_OK on success
* #GNUNET_SYSERR on internal error
*/
int
(*insert_lock) (void *cls,
struct TALER_MINTDB_Session *sesssion,
const struct TALER_MINTDB_LockOperation *lock);
/**
* Compile a list of all (historic) transactions performed
* with the given coin (/refresh/melt and /deposit operations).
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param sesssion database connection
* @param session database connection
* @param coin_pub coin to investigate
* @return list of transactions, NULL if coin is fresh
*/
struct TALER_MINTDB_TransactionList *
(*get_coin_transactions) (void *cls,
struct TALER_MINTDB_Session *sesssion,
struct TALER_MINTDB_Session *session,
const struct TALER_CoinSpendPublicKeyP *coin_pub);

View File

@ -653,13 +653,73 @@ struct TALER_MintKeyValidityPS
struct TALER_MasterPublicKeyP master;
/**
* Array of hash(es) of the mint's denomination keys.
* Specifically, this is the hash over the
* `struct TALER_DenominationKeyValidityPS`, not just
* the public key (as the auditor needs to check against
* the correct valuations and fee structure).
* Start time of the validity period for this key.
*/
/* struct GNUNET_HashCode h_dks; */
struct GNUNET_TIME_AbsoluteNBO start;
/**
* The mint will sign fresh coins between @e start and this time.
* @e expire_withdraw will be somewhat larger than @e start to
* ensure a sufficiently large anonymity set, while also allowing
* the Mint to limit the financial damage in case of a key being
* compromised. Thus, mints with low volume are expected to have a
* longer withdraw period (@e expire_withdraw - @e start) than mints
* with high transaction volume. The period may also differ between
* types of coins. A mint may also have a few denomination keys
* with the same value with overlapping validity periods, to address
* issues such as clock skew.
*/
struct GNUNET_TIME_AbsoluteNBO expire_withdraw;
/**
* Coins signed with the denomination key must be spent or refreshed
* between @e start and this expiration time. After this time, the
* mint will refuse transactions involving this key as it will
* "drop" the table with double-spending information (shortly after)
* this time. Note that wallets should refresh coins significantly
* before this time to be on the safe side. @e expire_spend must be
* significantly larger than @e expire_withdraw (by months or even
* years).
*/
struct GNUNET_TIME_AbsoluteNBO expire_spend;
/**
* When do signatures with this denomination key become invalid?
* After this point, these signatures cannot be used in (legal)
* disputes anymore, as the Mint is then allowed to destroy its side
* of the evidence. @e expire_legal is expected to be significantly
* larger than @e expire_spend (by a year or more).
*/
struct GNUNET_TIME_AbsoluteNBO expire_legal;
/**
* The value of the coins signed with this denomination key.
*/
struct TALER_AmountNBO value;
/**
* The fee the mint charges when a coin of this type is withdrawn.
* (can be zero).
*/
struct TALER_AmountNBO fee_withdraw;
/**
* The fee the mint charges when a coin of this type is deposited.
* (can be zero).
*/
struct TALER_AmountNBO fee_deposit;
/**
* The fee the mint charges when a coin of this type is refreshed.
* (can be zero).
*/
struct TALER_AmountNBO fee_refresh;
/**
* Hash code of the denomination public key. (Used to avoid having
* the variable-size RSA key in this struct.)
*/
struct GNUNET_HashCode denom_hash GNUNET_PACKED;
};

View File

@ -22,7 +22,8 @@ libtalermint_la_SOURCES = \
mint_api_deposit.c \
mint_api_refresh.c \
mint_api_refresh_link.c \
mint_api_withdraw.c
mint_api_reserve.c \
mint_api_wire.c
libtalermint_la_LIBADD = \
-lgnunetutil \

View File

@ -0,0 +1,34 @@
#!/bin/sh
#
# This file is part of TALER
# Copyright (C) 2015 GNUnet e.V.
#
# TALER is free software; you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free Software
# Foundation; either version 3, or (at your option) any later version.
#
# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License along with
# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
#
#
# This will generate testcases in a directory 'afl-tests', which can then
# be moved into src/mint/afl-tests/ to be run during mint-testing.
#
# This script uses American Fuzzy Loop (AFL) to fuzz the mint to
# automatically create tests with good coverage. You must install
# AFL and set AFL_HOME to the directory where AFL is installed
# before running. Also, a directory "baseline/" should exist with
# templates for inputs for AFL to fuzz. These can be generated
# by running wireshark on loopback while running 'make check' in
# this directory. Save each HTTP request to a new file.
#
# Note that you want to switch 'TESTRUN = NO' and pre-init the
# database before running this, otherwise it will be awfully slow.
#
# Must be run from this directory.
#
$AFL_HOME/afl-fuzz -i baseline/ -m 250 -o afl-tests/ -f /tmp/afl-input taler-mint-httpd -f /tmp/afl-input -d test-mint-home/ -C

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,8 @@
POST /deposit HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 1658
Expect: 100-continue
{"ub_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26E9M8S0M6CSH6X334GSN8RW30D9G8MT46CA660W34GSG6MT4AD9K8GT3ECSH6MVK0E2374V38H1M8MR4CDJ66MWK4E1S6MR3GCT28CV32H1Q8N23GCHG70S36C1K8MS3GCSN8RV36D9S710KGD9K6GWKEGJ28GRM4CJ56X1K6DJ18D2KGHA46D13GDA66GVK4GHJ8N13AE9J8RVK6GT184S48E1K6X336G9Q8N142CJ4692M6EA16GRKJD9N6523ADA36X13GG9G70TK6DHN68R36CT18GR4CDSJ6CW3GCT364W46CSR8RV42GJ474SMADSH851K4H9Q8GS42CHS8RV3GCSJ64V46DSN8RSM6HHN6N246D9S6934AH9P6X23JGSH652K0DJ5612KJGA26N242CH35452081918G2J2G0","timestamp":"/Date(1442821652)/","f":{"currency":"EUR","value":5,"fraction":0},"wire":{"type":"TEST","bank":"dest bank","account":42},"coin_pub":"JXWK4NS0H2W4V4BETQ90CCEDADP6QQ3MV3YZ7RV2KXEM8PWXE8Q0","H_wire":"YQED9FDYPKK2QQYB3FS19Y15ZMKBAXJP2C73CXASAF1KM6ZYY723TEJ3HBR6D864A7X5W58G92QJ0A9PFMZNB81ZP9NJAQQCCABM4RG","H_contract":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","transaction_id":1,"refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"}

View File

@ -0,0 +1,7 @@
GET /keys HTTP/1.1
User-Agent: Wget/1.16.3 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: 127.0.0.1:8081
Connection: Keep-Alive

View File

@ -0,0 +1,5 @@
GET /refresh/link?coin_pub=WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
POST /refresh/reveal HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 255
{"session_hash":"V97SB8T670M9V71D1Q0KVQ4GSJCVQ5AAKTTH9QKT0ZJZZBFNZAV4NA8NMWRRGVPFEBEGB6ANCN9BPQASJ40TM4Y1C49648TJJ07PGSG","transfer_privs":[["EQKJA401A9NJ2YJDFZJ1EV8AYXBHWZB6NT5T0TWSJHVKVDM6W8A0"],["TKDJ4DF3GZVG0DGAB9E3RGBGSTANYB6JVVWXJGPMB2AY4VQNTBA0"]]}

View File

@ -0,0 +1,4 @@
GET /reserve/status?reserve_pub=TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0 HTTP/1.1
Host: localhost:8081
Accept: */*

View File

@ -0,0 +1,7 @@
POST /reserve/withdraw HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 919
{"coin_ev":"Q5X8A8TCBFH7E5BMY7HSB17SHFTM1JPJGV61P2CA7Z9EXG8P2HYS69B31NZESKXHSZHNJ2DQN3CC2AWFNC6V90J577JD3TXBMAY8Y5M9V60KKT73Z1DW24JFSNAK91G1F2WT55ADP1EG7N5F9AY7A7ZJD03MPYSH0RDP7SVZS2KRPA5JRHFR4GDJ59CFNE7A43M95ZKQHQAS8","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","reserve_sig":"8427B3RTB217124EB1C37ZVJFC08KN17RHGHE9ENZQMQVJ0S11SAX6H8Z06SWCKT06DRQ9DQ8XD786XKQ94T27PYR9GC9EMT1Y02W10"}

View File

@ -0,0 +1,5 @@
GET /wire HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -0,0 +1,5 @@
GET /wire/sepa HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -0,0 +1,5 @@
GET /wire/test HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -435,6 +435,29 @@ MAC_download_get_result (struct MAC_DownloadBuffer *db,
{
json_t *json;
json_error_t error;
char *ct;
if ( (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_CONTENT_TYPE,
&ct)) ||
(NULL == ct) ||
(0 != strcasecmp (ct,
"application/json")) )
{
/* No content type or explicitly not JSON, refuse to parse
(but keep response code) */
if (CURLE_OK !=
curl_easy_getinfo (eh,
CURLINFO_RESPONSE_CODE,
response_code))
{
/* unexpected error... */
GNUNET_break (0);
*response_code = 0;
}
return NULL;
}
json = NULL;
if (0 == db->eno)

View File

@ -325,9 +325,11 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
&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->deposit_valid_until = deposit_valid_until;
denom_key->expire_legal = expire_legal;
denom_key->value = value;
denom_key->fee_withdraw = fee_withdraw;
denom_key->fee_deposit = fee_deposit;
@ -340,6 +342,116 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey *denom_key,
}
/**
* Parse a mint's auditor information encoded in JSON.
*
* @param[out] auditor where to return the result
* @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
* invalid or the json malformed.
*/
static int
parse_json_auditor (struct TALER_MINT_AuditorInformation *auditor,
json_t *auditor_obj,
const struct TALER_MINT_Keys *key_data)
{
json_t *keys;
json_t *key;
unsigned int len;
unsigned int off;
unsigned int i;
struct TALER_MintKeyValidityPS kv;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("auditor_pub",
&auditor->auditor_pub),
MAJ_spec_json ("denomination_keys",
&keys),
MAJ_spec_end
};
auditor->auditor_url = NULL; /* #3987 */
if (GNUNET_OK !=
MAJ_parse_json (auditor_obj,
spec))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
kv.master = key_data->master_pub;
len = json_array_size (keys);
auditor->denom_keys = GNUNET_new_array (len,
const struct TALER_MINT_DenomPublicKey *);
i = 0;
off = 0;
json_array_foreach (keys, i, key) {
struct TALER_AuditorSignatureP auditor_sig;
struct GNUNET_HashCode denom_h;
const struct TALER_MINT_DenomPublicKey *dk;
unsigned int j;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("denom_pub_h",
&denom_h),
MAJ_spec_fixed_auto ("auditor_sig",
&auditor_sig),
MAJ_spec_end
};
if (GNUNET_OK !=
MAJ_parse_json (key,
spec))
{
GNUNET_break_op (0);
continue;
}
dk = NULL;
for (j=0;j<key_data->num_denom_keys;j++)
{
if (0 == memcmp (&denom_h,
&key_data->denom_keys[j].h_key,
sizeof (struct GNUNET_HashCode)))
{
dk = &key_data->denom_keys[j];
break;
}
}
if (NULL == dk)
{
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_spend = GNUNET_TIME_absolute_hton (dk->deposit_valid_until);
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);
kv.denom_hash = dk->h_key;
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_MINT_KEYS,
&kv.purpose,
&auditor_sig.eddsa_sig,
&auditor->auditor_pub.eddsa_pub))
{
GNUNET_break_op (0);
continue;
}
auditor->denom_keys[off] = dk;
off++;
}
auditor->num_denom_keys = off;
return GNUNET_OK;
}
/**
* Decode the JSON in @a resp_obj from the /keys response and store the data
* in the @a key_data.
@ -394,8 +506,8 @@ decode_keys_json (json_t *resp_obj,
EXITIF (0 == (key_data->num_sign_keys =
json_array_size (sign_keys_array)));
key_data->sign_keys
= GNUNET_malloc (sizeof (struct TALER_MINT_SigningPublicKey)
* key_data->num_sign_keys);
= GNUNET_new_array (key_data->num_sign_keys,
struct TALER_MINT_SigningPublicKey);
index = 0;
json_array_foreach (sign_keys_array, index, sign_key_obj) {
EXITIF (GNUNET_SYSERR ==
@ -415,8 +527,8 @@ decode_keys_json (json_t *resp_obj,
json_object_get (resp_obj, "denoms")));
EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
EXITIF (0 == (key_data->num_denom_keys = json_array_size (denom_keys_array)));
key_data->denom_keys = GNUNET_malloc (sizeof (struct TALER_MINT_DenomPublicKey)
* key_data->num_denom_keys);
key_data->denom_keys = GNUNET_new_array (key_data->num_denom_keys,
struct TALER_MINT_DenomPublicKey);
index = 0;
json_array_foreach (denom_keys_array, index, denom_key_obj) {
EXITIF (GNUNET_SYSERR ==
@ -427,7 +539,30 @@ decode_keys_json (json_t *resp_obj,
}
}
/* FIXME: parse the auditor keys (#3847) */
/* parse the auditor information */
{
json_t *auditors_array;
json_t *auditor_info;
unsigned int len;
unsigned int index;
EXITIF (NULL == (auditors_array =
json_object_get (resp_obj, "auditors")));
EXITIF (JSON_ARRAY != json_typeof (auditors_array));
len = json_array_size (auditors_array);
if (0 != len)
{
key_data->auditors = GNUNET_new_array (len,
struct TALER_MINT_AuditorInformation);
index = 0;
json_array_foreach (auditors_array, index, auditor_info) {
EXITIF (GNUNET_SYSERR ==
parse_json_auditor (&key_data->auditors[index],
auditor_info,
key_data));
}
}
}
/* Validate signature... */
ks.purpose.size = htonl (sizeof (ks));
@ -551,7 +686,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h)
* Obtain the URL to use for an API request.
*
* @param h the mint handle to query
* @param path Taler API path (i.e. "/withdraw/sign")
* @param path Taler API path (i.e. "/reserve/withdraw")
* @return the full URI to use with cURL
*/
char *
@ -708,6 +843,28 @@ TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
}
/**
* Obtain the denomination key details from the mint.
*
* @param keys the mint's key set
* @param hc hash of the public key of the denomination to lookup
* @return details about the given denomination key
*/
const struct TALER_MINT_DenomPublicKey *
TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
const struct GNUNET_HashCode *hc)
{
unsigned int i;
for (i=0;i<keys->num_denom_keys;i++)
if (0 == memcmp (hc,
&keys->denom_keys[i].h_key,
sizeof (struct GNUNET_HashCode)))
return &keys->denom_keys[i];
return NULL;
}
/**
* Obtain the keys from the mint.
*

View File

@ -48,7 +48,7 @@ MAH_handle_is_ready (struct TALER_MINT_Handle *h);
* Obtain the URL to use for an API request.
*
* @param h the mint handle to query
* @param path Taler API path (i.e. "/withdraw/sign")
* @param path Taler API path (i.e. "/reserve/withdraw")
* @return the full URI to use with cURL
*/
char *

View File

@ -15,8 +15,8 @@
<http://www.gnu.org/licenses/>
*/
/**
* @file mint-lib/mint_api_withdraw.c
* @brief Implementation of the /withdraw requests of the mint's HTTP API
* @file mint-lib/mint_api_reserve.c
* @brief Implementation of the /reserve requests of the mint's HTTP API
* @author Christian Grothoff
*/
#include "platform.h"
@ -31,12 +31,12 @@
#include "taler_signatures.h"
/* ********************** /withdraw/status ********************** */
/* ********************** /reserve/status ********************** */
/**
* @brief A Withdraw Status Handle
*/
struct TALER_MINT_WithdrawStatusHandle
struct TALER_MINT_ReserveStatusHandle
{
/**
@ -57,7 +57,7 @@ struct TALER_MINT_WithdrawStatusHandle
/**
* Function to call with the result.
*/
TALER_MINT_WithdrawStatusResultCallback cb;
TALER_MINT_ReserveStatusResultCallback cb;
/**
* Public key of the reserve we are querying.
@ -264,16 +264,16 @@ parse_reserve_history (json_t *history,
/**
* Function called when we're done processing the
* HTTP /withdraw/status request.
* HTTP /reserve/status request.
*
* @param cls the `struct TALER_MINT_WithdrawStatusHandle`
* @param cls the `struct TALER_MINT_ReserveStatusHandle`
* @param eh curl handle of the request that finished
*/
static void
handle_withdraw_status_finished (void *cls,
CURL *eh)
handle_reserve_status_finished (void *cls,
CURL *eh)
{
struct TALER_MINT_WithdrawStatusHandle *wsh = cls;
struct TALER_MINT_ReserveStatusHandle *wsh = cls;
long response_code;
json_t *json;
@ -376,7 +376,7 @@ handle_withdraw_status_finished (void *cls,
NULL,
0, NULL);
json_decref (json);
TALER_MINT_withdraw_status_cancel (wsh);
TALER_MINT_reserve_status_cancel (wsh);
}
@ -396,13 +396,13 @@ handle_withdraw_status_finished (void *cls,
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawStatusHandle *
TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_MINT_WithdrawStatusResultCallback cb,
void *cb_cls)
struct TALER_MINT_ReserveStatusHandle *
TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_MINT_ReserveStatusResultCallback cb,
void *cb_cls)
{
struct TALER_MINT_WithdrawStatusHandle *wsh;
struct TALER_MINT_ReserveStatusHandle *wsh;
struct TALER_MINT_Context *ctx;
CURL *eh;
char *pub_str;
@ -417,10 +417,10 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
pub_str = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
sizeof (struct TALER_ReservePublicKeyP));
GNUNET_asprintf (&arg_str,
"/withdraw/status?reserve_pub=%s",
"/reserve/status?reserve_pub=%s",
pub_str);
GNUNET_free (pub_str);
wsh = GNUNET_new (struct TALER_MINT_WithdrawStatusHandle);
wsh = GNUNET_new (struct TALER_MINT_ReserveStatusHandle);
wsh->mint = mint;
wsh->cb = cb;
wsh->cb_cls = cb_cls;
@ -446,7 +446,7 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
wsh->job = MAC_job_add (ctx,
eh,
GNUNET_NO,
&handle_withdraw_status_finished,
&handle_reserve_status_finished,
wsh);
return wsh;
}
@ -459,7 +459,7 @@ TALER_MINT_withdraw_status (struct TALER_MINT_Handle *mint,
* @param wsh the withdraw status request handle
*/
void
TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh)
{
if (NULL != wsh->job)
{
@ -472,12 +472,12 @@ TALER_MINT_withdraw_status_cancel (struct TALER_MINT_WithdrawStatusHandle *wsh)
}
/* ********************** /withdraw/sign ********************** */
/* ********************** /reserve/withdraw ********************** */
/**
* @brief A Withdraw Sign Handle
*/
struct TALER_MINT_WithdrawSignHandle
struct TALER_MINT_ReserveWithdrawHandle
{
/**
@ -503,7 +503,7 @@ struct TALER_MINT_WithdrawSignHandle
/**
* Function to call with the result.
*/
TALER_MINT_WithdrawSignResultCallback cb;
TALER_MINT_ReserveWithdrawResultCallback cb;
/**
* Key used to blind the value.
@ -539,7 +539,7 @@ struct TALER_MINT_WithdrawSignHandle
/**
* We got a 200 OK response for the /withdraw/sign operation.
* We got a 200 OK response for the /reserve/withdraw operation.
* Extract the coin's signature and return it to the caller.
* The signature we get from the mint is for the blinded value.
* Thus, we first must unblind it and then should verify its
@ -553,7 +553,7 @@ struct TALER_MINT_WithdrawSignHandle
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/
static int
withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
reserve_withdraw_ok (struct TALER_MINT_ReserveWithdrawHandle *wsh,
json_t *json)
{
struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
@ -598,7 +598,7 @@ withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
/**
* We got a 402 PAYMENT REQUIRED response for the /withdraw/sign operation.
* We got a 402 PAYMENT REQUIRED response for the /reserve/withdraw operation.
* Check the signatures on the withdraw transactions in the provided
* history and that the balances add up. We don't do anything directly
* with the information, as the JSON will be returned to the application.
@ -610,8 +610,8 @@ withdraw_sign_ok (struct TALER_MINT_WithdrawSignHandle *wsh,
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/
static int
withdraw_sign_payment_required (struct TALER_MINT_WithdrawSignHandle *wsh,
json_t *json)
reserve_withdraw_payment_required (struct TALER_MINT_ReserveWithdrawHandle *wsh,
json_t *json)
{
struct TALER_Amount balance;
struct TALER_Amount balance_from_history;
@ -690,16 +690,16 @@ withdraw_sign_payment_required (struct TALER_MINT_WithdrawSignHandle *wsh,
/**
* Function called when we're done processing the
* HTTP /withdraw/sign request.
* HTTP /reserve/withdraw request.
*
* @param cls the `struct TALER_MINT_WithdrawSignHandle`
* @param cls the `struct TALER_MINT_ReserveWithdrawHandle`
* @param eh curl handle of the request that finished
*/
static void
handle_withdraw_sign_finished (void *cls,
CURL *eh)
handle_reserve_withdraw_finished (void *cls,
CURL *eh)
{
struct TALER_MINT_WithdrawSignHandle *wsh = cls;
struct TALER_MINT_ReserveWithdrawHandle *wsh = cls;
long response_code;
json_t *json;
@ -713,7 +713,7 @@ handle_withdraw_sign_finished (void *cls,
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
withdraw_sign_ok (wsh,
reserve_withdraw_ok (wsh,
json))
{
GNUNET_break_op (0);
@ -728,7 +728,7 @@ handle_withdraw_sign_finished (void *cls,
/* The mint says that the reserve has insufficient funds;
check the signatures in the history... */
if (GNUNET_OK !=
withdraw_sign_payment_required (wsh,
reserve_withdraw_payment_required (wsh,
json))
{
GNUNET_break_op (0);
@ -766,12 +766,12 @@ handle_withdraw_sign_finished (void *cls,
NULL,
json);
json_decref (json);
TALER_MINT_withdraw_sign_cancel (wsh);
TALER_MINT_reserve_withdraw_cancel (wsh);
}
/**
* Withdraw a coin from the mint using a /withdraw/sign request. Note
* Withdraw a coin from the mint using a /reserve/withdraw request. Note
* that to ensure that no money is lost in case of hardware failures,
* the caller must have committed (most of) the arguments to disk
* before calling, and be ready to repeat the request with the same
@ -790,16 +790,16 @@ handle_withdraw_sign_finished (void *cls,
* if the inputs are invalid (i.e. denomination key not with this mint).
* In this case, the callback is not called.
*/
struct TALER_MINT_WithdrawSignHandle *
TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
const struct TALER_MINT_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_MINT_WithdrawSignResultCallback res_cb,
void *res_cb_cls)
struct TALER_MINT_ReserveWithdrawHandle *
TALER_MINT_reserve_withdraw (struct TALER_MINT_Handle *mint,
const struct TALER_MINT_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_MINT_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls)
{
struct TALER_MINT_WithdrawSignHandle *wsh;
struct TALER_MINT_ReserveWithdrawHandle *wsh;
struct TALER_WithdrawRequestPS req;
struct TALER_ReserveSignatureP reserve_sig;
struct TALER_CoinSpendPublicKeyP coin_pub;
@ -810,7 +810,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
json_t *withdraw_obj;
CURL *eh;
wsh = GNUNET_new (struct TALER_MINT_WithdrawSignHandle);
wsh = GNUNET_new (struct TALER_MINT_ReserveWithdrawHandle);
wsh->mint = mint;
wsh->cb = res_cb;
wsh->cb_cls = res_cb_cls;
@ -866,7 +866,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
GNUNET_free (coin_ev);
wsh->blinding_key = blinding_key;
wsh->url = MAH_path_to_url (mint, "/withdraw/sign");
wsh->url = MAH_path_to_url (mint, "/reserve/withdraw");
eh = curl_easy_init ();
GNUNET_assert (NULL != (wsh->json_enc =
@ -897,7 +897,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
wsh->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_withdraw_sign_finished,
&handle_reserve_withdraw_finished,
wsh);
return wsh;
}
@ -910,7 +910,7 @@ TALER_MINT_withdraw_sign (struct TALER_MINT_Handle *mint,
* @param sign the withdraw sign request handle
*/
void
TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
TALER_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign)
{
if (NULL != sign->job)
{
@ -924,4 +924,4 @@ TALER_MINT_withdraw_sign_cancel (struct TALER_MINT_WithdrawSignHandle *sign)
}
/* end of mint_api_withdraw.c */
/* end of mint_api_reserve.c */

View File

@ -0,0 +1,619 @@
/*
This file is part of TALER
Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
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
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file mint-lib/mint_api_wire.c
* @brief Implementation of the /wire request of the mint's HTTP API
* @author Christian Grothoff
*/
#include "platform.h"
#include <curl/curl.h>
#include <jansson.h>
#include <microhttpd.h> /* just for HTTP status codes */
#include <gnunet/gnunet_util_lib.h>
#include "taler_mint_service.h"
#include "mint_api_common.h"
#include "mint_api_json.h"
#include "mint_api_context.h"
#include "mint_api_handle.h"
#include "taler_signatures.h"
/**
* @brief A Wire Handle
*/
struct TALER_MINT_WireHandle
{
/**
* The connection to mint this request handle will use
*/
struct TALER_MINT_Handle *mint;
/**
* The url for this request.
*/
char *url;
/**
* Handle for the request.
*/
struct MAC_Job *job;
/**
* Function to call with the result.
*/
TALER_MINT_WireResultCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Download buffer
*/
struct MAC_DownloadBuffer db;
/**
* Set to the "methods" JSON array returned by the
* /wire request.
*/
json_t *methods;
/**
* Current iteration offset in the @e methods array.
*/
unsigned int methods_off;
};
/**
* Verify that the signature on the "200 OK" response
* for /wire/sepa from the mint is valid.
*
* @param wh wire handle
* @param json json reply with the signature
* @return #GNUNET_SYSERR if @a json is invalid,
* #GNUNET_NO if the method is unknown,
* #GNUNET_OK if the json is valid
*/
static int
verify_wire_sepa_signature_ok (const struct TALER_MINT_WireHandle *wh,
json_t *json)
{
struct TALER_MasterSignatureP mint_sig;
struct TALER_MasterWireSepaDetailsPS mp;
const char *receiver_name;
const char *iban;
const char *bic;
const struct TALER_MINT_Keys *key_state;
struct GNUNET_HashContext *hc;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("sig", &mint_sig),
MAJ_spec_string ("receiver_name", &receiver_name),
MAJ_spec_string ("iban", &iban),
MAJ_spec_string ("bic", &bic),
MAJ_spec_end
};
if (GNUNET_OK !=
MAJ_parse_json (json,
spec))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
key_state = TALER_MINT_get_keys (wh->mint);
mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS));
hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc,
receiver_name,
strlen (receiver_name) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
iban,
strlen (iban) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
bic,
strlen (bic) + 1);
GNUNET_CRYPTO_hash_context_finish (hc,
&mp.h_sepa_details);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
&mp.purpose,
&mint_sig.eddsa_signature,
&key_state->master_pub.eddsa_pub))
{
GNUNET_break_op (0);
MAJ_parse_free (spec);
return GNUNET_SYSERR;
}
MAJ_parse_free (spec);
return GNUNET_OK;
}
/**
* Verify that the signature on the "200 OK" response
* for /wire/METHOD from the mint is valid.
*
* @param wh wire handle with key material
* @param method method to verify the reply for
* @param json json reply with the signature
* @return #GNUNET_SYSERR if @a json is invalid,
* #GNUNET_NO if the method is unknown,
* #GNUNET_OK if the json is valid
*/
static int
verify_wire_method_signature_ok (const struct TALER_MINT_WireHandle *wh,
const char *method,
json_t *json)
{
struct
{
/**
* Name fo the method.
*/
const char *method;
/**
* Handler to invoke to verify signature.
*
* @param wh wire handle with key material
* @param json json reply with signature to verify
*/
int (*handler)(const struct TALER_MINT_WireHandle *wh,
json_t *json);
} handlers[] = {
{ "sepa", &verify_wire_sepa_signature_ok },
{ NULL, NULL }
};
unsigned int i;
for (i=0;NULL != handlers[i].method; i++)
if (0 == strcasecmp (handlers[i].method,
method))
return handlers[i].handler (wh,
json);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wire transfer method `%s' not supported\n",
method);
return GNUNET_NO;
}
/**
* Perform the next /wire/method request or signal
* the end of the iteration.
*
* @param wh the wire handle
* @return a handle for this request
*/
static void
request_wire_method (struct TALER_MINT_WireHandle *wh);
/**
* Function called when we're done processing the
* HTTP /wire/METHOD request.
*
* @param cls the `struct TALER_MINT_WireHandle`
* @param eh the curl request handle
*/
static void
handle_wire_method_finished (void *cls,
CURL *eh)
{
struct TALER_MINT_WireHandle *wh = cls;
long response_code;
json_t *json;
wh->job = NULL;
json = MAC_download_get_result (&wh->db,
eh,
&response_code);
switch (response_code)
{
case 0:
break;
case MHD_HTTP_OK:
{
const char *method;
method = json_string_value (json_array_get (wh->methods,
wh->methods_off - 1));
if (GNUNET_OK !=
verify_wire_method_signature_ok (wh,
method,
json))
{
GNUNET_break_op (0);
response_code = 0;
break;
}
break;
}
case MHD_HTTP_FOUND:
/* /wire/test returns a 302 redirect, we should just give
this information back to the callback below */
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the mint is buggy
(or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
GNUNET_break (0);
response_code = 0;
break;
}
if (0 == response_code)
{
/* signal end of iteration */
wh->cb (wh->cb_cls,
0,
NULL,
NULL);
json_decref (json);
TALER_MINT_wire_cancel (wh);
return;
}
/* pass on successful reply */
wh->cb (wh->cb_cls,
response_code,
json_string_value (json_array_get (wh->methods,
wh->methods_off-1)),
json);
/* trigger request for the next /wire/method */
request_wire_method (wh);
}
/**
* Perform the next /wire/method request or signal
* the end of the iteration.
*
* @param wh the wire handle
* @return a handle for this request
*/
static void
request_wire_method (struct TALER_MINT_WireHandle *wh)
{
struct TALER_MINT_Context *ctx;
CURL *eh;
char *path;
if (json_array_size (wh->methods) <= wh->methods_off)
{
/* we are done, signal end of iteration */
wh->cb (wh->cb_cls,
0,
NULL,
NULL);
TALER_MINT_wire_cancel (wh);
return;
}
GNUNET_free_non_null (wh->db.buf);
wh->db.buf = NULL;
wh->db.buf_size = 0;
wh->db.eno = 0;
GNUNET_free_non_null (wh->url);
GNUNET_asprintf (&path,
"/wire/%s",
json_string_value (json_array_get (wh->methods,
wh->methods_off++)));
wh->url = MAH_path_to_url (wh->mint,
path);
GNUNET_free (path);
eh = curl_easy_init ();
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_URL,
wh->url));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
&wh->db));
/* The default is 'disabled', but let's be sure */
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_FOLLOWLOCATION,
(long) 0));
ctx = MAH_handle_to_context (wh->mint);
wh->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_wire_method_finished,
wh);
}
/**
* Verify that the signature on the "200 OK" response
* for /wire from the mint is valid.
*
* @param wh wire handle
* @param json json reply with the signature
* @return NULL if @a json is invalid, otherwise the
* "methods" array (with an RC of 1)
*/
static json_t *
verify_wire_signature_ok (const struct TALER_MINT_WireHandle *wh,
json_t *json)
{
struct TALER_MintSignatureP mint_sig;
struct TALER_MintPublicKeyP mint_pub;
struct TALER_MintWireSupportMethodsPS mp;
json_t *methods;
const struct TALER_MINT_Keys *key_state;
struct GNUNET_HashContext *hc;
struct MAJ_Specification spec[] = {
MAJ_spec_fixed_auto ("sig", &mint_sig),
MAJ_spec_fixed_auto ("pub", &mint_pub),
MAJ_spec_json ("methods", &methods),
MAJ_spec_end
};
unsigned int i;
if (GNUNET_OK !=
MAJ_parse_json (json,
spec))
{
GNUNET_break_op (0);
return NULL;
}
if (! json_is_array (methods))
{
GNUNET_break_op (0);
MAJ_parse_free (spec);
return NULL;
}
key_state = TALER_MINT_get_keys (wh->mint);
if (GNUNET_OK !=
TALER_MINT_test_signing_key (key_state,
&mint_pub))
{
GNUNET_break_op (0);
return NULL;
}
hc = GNUNET_CRYPTO_hash_context_start ();
for (i=0;i<json_array_size (methods);i++)
{
const json_t *element = json_array_get (methods, i);
const char *method;
if (! json_is_string (element))
{
GNUNET_CRYPTO_hash_context_abort (hc);
GNUNET_break_op (0);
MAJ_parse_free (spec);
return NULL;
}
method = json_string_value (element);
GNUNET_CRYPTO_hash_context_read (hc,
method,
strlen (method) + 1);
}
mp.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES);
mp.purpose.size = htonl (sizeof (struct TALER_MintWireSupportMethodsPS));
GNUNET_CRYPTO_hash_context_finish (hc,
&mp.h_wire_types);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_WIRE_TYPES,
&mp.purpose,
&mint_sig.eddsa_signature,
&mint_pub.eddsa_pub))
{
GNUNET_break_op (0);
MAJ_parse_free (spec);
return NULL;
}
return methods;
}
/**
* Function called when we're done processing the
* HTTP /wire request.
*
* @param cls the `struct TALER_MINT_WireHandle`
* @param eh the curl request handle
*/
static void
handle_wire_finished (void *cls,
CURL *eh)
{
struct TALER_MINT_WireHandle *wh = cls;
long response_code;
json_t *json;
wh->job = NULL;
json = MAC_download_get_result (&wh->db,
eh,
&response_code);
switch (response_code)
{
case 0:
break;
case MHD_HTTP_OK:
{
json_t *methods;
if (NULL ==
(methods = verify_wire_signature_ok (wh,
json)))
{
GNUNET_break_op (0);
response_code = 0;
break;
}
wh->methods = methods;
request_wire_method (wh);
return;
}
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the mint is buggy
(or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
break;
default:
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u\n",
response_code);
GNUNET_break (0);
response_code = 0;
break;
}
if (0 != response_code)
{
/* pass on successful reply */
wh->cb (wh->cb_cls,
response_code,
NULL,
json);
}
/* signal end of iteration */
wh->cb (wh->cb_cls,
0,
NULL,
NULL);
if (NULL != json)
json_decref (json);
TALER_MINT_wire_cancel (wh);
}
/**
* Obtain information about a mint's wire instructions.
* A mint may provide wire instructions for creating
* a reserve. The wire instructions also indicate
* which wire formats merchants may use with the mint.
* This API is typically used by a wallet for wiring
* funds, and possibly by a merchant to determine
* supported wire formats.
*
* Note that while we return the (main) response verbatim to the
* caller for further processing, we do already verify that the
* response is well-formed (i.e. that signatures included in the
* response are all valid). If the mint's reply is not well-formed,
* we return an HTTP status code of zero to @a cb.
*
* @param mint the mint handle; the mint must be ready to operate
* @param wire_cb the callback to call when a reply for this request is available
* @param wire_cb_cls closure for the above callback
* @return a handle for this request
*/
struct TALER_MINT_WireHandle *
TALER_MINT_wire (struct TALER_MINT_Handle *mint,
TALER_MINT_WireResultCallback wire_cb,
void *wire_cb_cls)
{
struct TALER_MINT_WireHandle *wh;
struct TALER_MINT_Context *ctx;
CURL *eh;
if (GNUNET_YES !=
MAH_handle_is_ready (mint))
{
GNUNET_break (0);
return NULL;
}
wh = GNUNET_new (struct TALER_MINT_WireHandle);
wh->mint = mint;
wh->cb = wire_cb;
wh->cb_cls = wire_cb_cls;
wh->url = MAH_path_to_url (mint, "/wire");
eh = curl_easy_init ();
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_URL,
wh->url));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEFUNCTION,
&MAC_download_cb));
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_WRITEDATA,
&wh->db));
ctx = MAH_handle_to_context (mint);
wh->job = MAC_job_add (ctx,
eh,
GNUNET_YES,
&handle_wire_finished,
wh);
return wh;
}
/**
* Cancel a wire information request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param wire the wire information request handle
*/
void
TALER_MINT_wire_cancel (struct TALER_MINT_WireHandle *wire)
{
if (NULL != wire->job)
{
MAC_job_cancel (wire->job);
wire->job = NULL;
}
if (NULL != wire->methods)
{
json_decref (wire->methods);
wire->methods = NULL;
}
GNUNET_free_non_null (wire->db.buf);
GNUNET_free (wire->url);
GNUNET_free (wire);
}
/* end of mint_api_wire.c */

View File

@ -2,9 +2,10 @@
# Currency supported by the mint (can only be one)
CURRENCY = EUR
# Wire format supproted by the mint
# TEST is used for testing... (what a shock)
WIREFORMAT = TEST
# Wire format supported by the mint
# We use 'test' for testing of the actual
# coin operations, and 'sepa' to test SEPA-specific routines.
WIREFORMAT = test sepa
# HTTP port the mint listens to
PORT = 8081
@ -15,9 +16,15 @@ MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
# How to access our database
DB = postgres
# This is a testcase, use transient DB actions
TESTRUN = YES
# Is this is a testcase, use transient DB actions?
TESTRUN = NO
[mintdb-postgres]
DB_CONN_STR = "postgres:///talercheck"
[mint-wire-sepa]
SEPA_RESPONSE_FILE = "test-mint-home/sepa.json"
[mint-wire-test]
REDIRECT_URL = "http://www.taler.net/"

View File

@ -0,0 +1,6 @@
{
"receiver_name": "Max Mustermann",
"iban": "DE89370400440532013000",
"bic": "COBADEFF370",
"sig": "8M5YJXM68PRAXKH76HYEBCJW657B23JA0RFGNDMZK2379YZMT626H1BN89KC0M1KJBWGYEN5Z763Q0Y7MCTZQ6BPPT7D9KFCTW60C10"
}

View File

@ -26,6 +26,15 @@
#include <gnunet/gnunet_util_lib.h>
#include <microhttpd.h>
/**
* Is the configuration file is set to include wire format 'test'?
*/
#define WIRE_TEST 1
/**
* Is the configuration file is set to include wire format 'sepa'?
*/
#define WIRE_SEPA 1
/**
* Main execution context for the main loop.
@ -97,7 +106,12 @@ enum OpCode
* Verify mint's /refresh/link by linking original private key to
* results from #OC_REFRESH_REVEAL step.
*/
OC_REFRESH_LINK
OC_REFRESH_LINK,
/**
* Verify the mint's /wire-method.
*/
OC_WIRE
};
@ -116,7 +130,7 @@ struct MeltDetails
const char *amount;
/**
* Reference to withdraw_sign operations for coin to
* Reference to reserve_withdraw operations for coin to
* be used for the /refresh/melt operation.
*/
const char *coin_ref;
@ -228,14 +242,14 @@ struct Command
/**
* Set to the API's handle during the operation.
*/
struct TALER_MINT_WithdrawStatusHandle *wsh;
struct TALER_MINT_ReserveStatusHandle *wsh;
/**
* Expected reserve balance.
*/
const char *expected_balance;
} withdraw_status;
} reserve_status;
/**
* Information for a #OC_WITHDRAW_SIGN command.
@ -281,9 +295,9 @@ struct Command
/**
* Withdraw handle (while operation is running).
*/
struct TALER_MINT_WithdrawSignHandle *wsh;
struct TALER_MINT_ReserveWithdrawHandle *wsh;
} withdraw_sign;
} reserve_withdraw;
/**
* Information for a #OC_DEPOSIT command.
@ -297,7 +311,7 @@ struct Command
const char *amount;
/**
* Reference to a withdraw_sign operation for a coin to
* Reference to a reserve_withdraw operation for a coin to
* be used for the /deposit operation.
*/
const char *coin_ref;
@ -439,6 +453,23 @@ struct Command
} refresh_link;
/**
* Information for the /wire command.
*/
struct {
/**
* Handle to the wire request.
*/
struct TALER_MINT_WireHandle *wh;
/**
* Format we expect to see, others will be *ignored*.
*/
const char *format;
} wire;
} details;
};
@ -622,8 +653,8 @@ compare_admin_add_incoming_history (const struct TALER_MINT_ReserveHistory *h,
* @return #GNUNET_OK if they match, #GNUNET_SYSERR if not
*/
static int
compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
const struct Command *cmd)
compare_reserve_withdraw_history (const struct TALER_MINT_ReserveHistory *h,
const struct Command *cmd)
{
struct TALER_Amount amount;
struct TALER_Amount amount_with_fee;
@ -634,12 +665,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (cmd->details.withdraw_sign.amount,
TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
&amount));
GNUNET_assert (GNUNET_OK ==
TALER_amount_add (&amount_with_fee,
&amount,
&cmd->details.withdraw_sign.pk->fee_withdraw));
&cmd->details.reserve_withdraw.pk->fee_withdraw));
if (0 != TALER_amount_cmp (&amount_with_fee,
&h->amount))
{
@ -651,7 +682,7 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
/**
* Function called with the result of a /withdraw/status request.
* Function called with the result of a /reserve/status request.
*
* @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
@ -662,12 +693,12 @@ compare_withdraw_sign_history (const struct TALER_MINT_ReserveHistory *h,
* @param history detailed transaction history, NULL on error
*/
static void
withdraw_status_cb (void *cls,
unsigned int http_status,
json_t *json,
const struct TALER_Amount *balance,
unsigned int history_length,
const struct TALER_MINT_ReserveHistory *history)
reserve_status_cb (void *cls,
unsigned int http_status,
json_t *json,
const struct TALER_Amount *balance,
unsigned int history_length,
const struct TALER_MINT_ReserveHistory *history)
{
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
@ -676,7 +707,7 @@ withdraw_status_cb (void *cls,
unsigned int j;
struct TALER_Amount amount;
cmd->details.withdraw_status.wsh = NULL;
cmd->details.reserve_status.wsh = NULL;
if (cmd->expected_response_code != http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@ -700,10 +731,10 @@ withdraw_status_cb (void *cls,
{
case OC_ADMIN_ADD_INCOMING:
if ( ( (NULL != rel->label) &&
(0 == strcmp (cmd->details.withdraw_status.reserve_reference,
(0 == strcmp (cmd->details.reserve_status.reserve_reference,
rel->label) ) ) ||
( (NULL != rel->details.admin_add_incoming.reserve_reference) &&
(0 == strcmp (cmd->details.withdraw_status.reserve_reference,
(0 == strcmp (cmd->details.reserve_status.reserve_reference,
rel->details.admin_add_incoming.reserve_reference) ) ) )
{
if (GNUNET_OK !=
@ -718,11 +749,11 @@ withdraw_status_cb (void *cls,
}
break;
case OC_WITHDRAW_SIGN:
if (0 == strcmp (cmd->details.withdraw_status.reserve_reference,
rel->details.withdraw_sign.reserve_reference))
if (0 == strcmp (cmd->details.reserve_status.reserve_reference,
rel->details.reserve_withdraw.reserve_reference))
{
if (GNUNET_OK !=
compare_withdraw_sign_history (&history[j],
compare_reserve_withdraw_history (&history[j],
rel))
{
GNUNET_break (0);
@ -743,10 +774,10 @@ withdraw_status_cb (void *cls,
fail (is);
return;
}
if (NULL != cmd->details.withdraw_status.expected_balance)
if (NULL != cmd->details.reserve_status.expected_balance)
{
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (cmd->details.withdraw_status.expected_balance,
TALER_string_to_amount (cmd->details.reserve_status.expected_balance,
&amount));
if (0 != TALER_amount_cmp (&amount,
balance))
@ -769,7 +800,7 @@ withdraw_status_cb (void *cls,
/**
* Function called upon completion of our /withdraw/sign request.
* Function called upon completion of our /reserve/withdraw request.
*
* @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
@ -778,15 +809,15 @@ withdraw_status_cb (void *cls,
* @param full_response full response from the mint (for logging, in case of errors)
*/
static void
withdraw_sign_cb (void *cls,
unsigned int http_status,
const struct TALER_DenominationSignature *sig,
json_t *full_response)
reserve_withdraw_cb (void *cls,
unsigned int http_status,
const struct TALER_DenominationSignature *sig,
json_t *full_response)
{
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
cmd->details.withdraw_sign.wsh = NULL;
cmd->details.reserve_withdraw.wsh = NULL;
if (cmd->expected_response_code != http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@ -807,7 +838,7 @@ withdraw_sign_cb (void *cls,
fail (is);
return;
}
cmd->details.withdraw_sign.sig.rsa_signature
cmd->details.reserve_withdraw.sig.rsa_signature
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
break;
case MHD_HTTP_PAYMENT_REQUIRED:
@ -1011,10 +1042,6 @@ link_cb (void *cls,
return;
}
/* check that the coins match */
fprintf (stderr,
"Got %u coins\n",
num_coins);
for (i=0;i<num_coins;i++)
for (j=i+1;j<num_coins;j++)
if (0 == memcmp (&coin_privs[i],
@ -1027,7 +1054,7 @@ link_cb (void *cls,
for (j=0;j<num_coins;j++)
{
const struct FreshCoin *fc;
fc = &ref->details.refresh_reveal.fresh_coins[j];
if ( (0 == memcmp (&coin_privs[i],
&fc->coin_priv,
@ -1048,8 +1075,8 @@ link_cb (void *cls,
found,
num_coins);
GNUNET_break (0);
fail (is);
return;
fail (is);
return;
}
break;
default:
@ -1115,6 +1142,83 @@ find_pk (const struct TALER_MINT_Keys *keys,
}
/**
* Callbacks called with the result(s) of a
* wire format inquiry request to the mint.
*
* The callback is invoked multiple times, once for each supported @a
* method. Finally, it is invoked one more time with cls/0/NULL/NULL
* to indicate the end of the iteration. If any request fails to
* generate a valid response from the mint, @a http_status will also
* be zero and the iteration will also end. Thus, the iteration
* always ends with a final call with an @a http_status of 0. If the
* @a http_status is already 0 on the first call, then the response to
* the /wire request was invalid. Later, clients can tell the
* difference between @a http_status of 0 indicating a failed
* /wire/method request and a regular end of the iteration by @a
* method being non-NULL. If the mint simply correctly asserts that
* it does not support any methods, @a method will be NULL but the @a
* http_status will be #MHD_HTTP_OK for the first call (followed by a
* cls/0/NULL/NULL call to signal the end of the iteration).
*
* @param cls closure with the interpreter state
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
* 0 if the mint's reply is bogus (fails to follow the protocol)
* @param method wire format method supported, i.e. "test" or "sepa", or NULL
* if already the /wire request failed.
* @param obj the received JSON reply, if successful this should be the wire
* format details as provided by /wire/METHOD/, or NULL if the
* reply was not in JSON format (in this case, the client might
* want to do an HTTP request to /wire/METHOD/ with a browser to
* provide more information to the user about the @a method).
*/
static void
wire_cb (void *cls,
unsigned int http_status,
const char *method,
json_t *obj)
{
struct InterpreterState *is = cls;
struct Command *cmd = &is->commands[is->ip];
if (0 == http_status)
{
/* 0 always signals the end of the iteration */
cmd->details.wire.wh = NULL;
}
else if ( (NULL != method) &&
(0 != strcasecmp (method,
cmd->details.wire.format)) )
{
/* not the method we care about, skip */
return;
}
if (cmd->expected_response_code != http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s/%s\n",
http_status,
cmd->label,
method);
json_dumpf (obj, stderr, 0);
fail (is);
return;
}
if (0 == http_status)
{
/* end of iteration, move to next command */
is->ip++;
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
is);
return;
}
/* For now, we only support to be called only once
with a "positive" result; so we switch to an
expected value of 0 for the 2nd iteration */
cmd->expected_response_code = 0;
}
/**
* Run the main interpreter loop that performs mint operations.
*
@ -1212,44 +1316,44 @@ interpreter_run (void *cls,
return;
case OC_WITHDRAW_STATUS:
GNUNET_assert (NULL !=
cmd->details.withdraw_status.reserve_reference);
cmd->details.reserve_status.reserve_reference);
ref = find_command (is,
cmd->details.withdraw_status.reserve_reference);
cmd->details.reserve_status.reserve_reference);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
GNUNET_CRYPTO_eddsa_key_get_public (&ref->details.admin_add_incoming.reserve_priv.eddsa_priv,
&reserve_pub.eddsa_pub);
cmd->details.withdraw_status.wsh
= TALER_MINT_withdraw_status (mint,
&reserve_pub,
&withdraw_status_cb,
is);
cmd->details.reserve_status.wsh
= TALER_MINT_reserve_status (mint,
&reserve_pub,
&reserve_status_cb,
is);
trigger_context_task ();
return;
case OC_WITHDRAW_SIGN:
GNUNET_assert (NULL !=
cmd->details.withdraw_sign.reserve_reference);
cmd->details.reserve_withdraw.reserve_reference);
ref = find_command (is,
cmd->details.withdraw_sign.reserve_reference);
cmd->details.reserve_withdraw.reserve_reference);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
if (NULL != cmd->details.withdraw_sign.amount)
if (NULL != cmd->details.reserve_withdraw.amount)
{
if (GNUNET_OK !=
TALER_string_to_amount (cmd->details.withdraw_sign.amount,
TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
&amount))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
cmd->details.withdraw_sign.amount,
cmd->details.reserve_withdraw.amount,
is->ip);
fail (is);
return;
}
cmd->details.withdraw_sign.pk = find_pk (is->keys,
&amount);
cmd->details.reserve_withdraw.pk = find_pk (is->keys,
&amount);
}
if (NULL == cmd->details.withdraw_sign.pk)
if (NULL == cmd->details.reserve_withdraw.pk)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to determine denomination key at %u\n",
@ -1263,23 +1367,22 @@ interpreter_run (void *cls,
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
priv = GNUNET_CRYPTO_eddsa_key_create ();
cmd->details.withdraw_sign.coin_priv.eddsa_priv = *priv;
cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
GNUNET_free (priv);
}
GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.withdraw_sign.coin_priv.eddsa_priv,
GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
&coin_pub.eddsa_pub);
cmd->details.withdraw_sign.blinding_key.rsa_blinding_key
= GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.withdraw_sign.pk->key.rsa_public_key));
cmd->details.withdraw_sign.wsh
= TALER_MINT_withdraw_sign (mint,
cmd->details.withdraw_sign.pk,
&ref->details.admin_add_incoming.reserve_priv,
&cmd->details.withdraw_sign.coin_priv,
&cmd->details.withdraw_sign.blinding_key,
&withdraw_sign_cb,
is);
if (NULL == cmd->details.withdraw_sign.wsh)
cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key
= GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.reserve_withdraw.pk->key.rsa_public_key));
cmd->details.reserve_withdraw.wsh
= TALER_MINT_reserve_withdraw (mint,
cmd->details.reserve_withdraw.pk,
&ref->details.admin_add_incoming.reserve_priv,
&cmd->details.reserve_withdraw.coin_priv,
&cmd->details.reserve_withdraw.blinding_key,
&reserve_withdraw_cb,
is);
if (NULL == cmd->details.reserve_withdraw.wsh)
{
GNUNET_break (0);
fail (is);
@ -1308,9 +1411,9 @@ interpreter_run (void *cls,
switch (ref->oc)
{
case OC_WITHDRAW_SIGN:
coin_priv = &ref->details.withdraw_sign.coin_priv;
coin_pk = ref->details.withdraw_sign.pk;
coin_pk_sig = &ref->details.withdraw_sign.sig;
coin_priv = &ref->details.reserve_withdraw.coin_priv;
coin_pk = ref->details.reserve_withdraw.pk;
coin_pk_sig = &ref->details.reserve_withdraw.sig;
break;
case OC_REFRESH_REVEAL:
{
@ -1355,7 +1458,6 @@ interpreter_run (void *cls,
fail (is);
return;
}
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
&coin_pub.eddsa_pub);
@ -1377,6 +1479,7 @@ interpreter_run (void *cls,
{
struct TALER_DepositRequestPS dr;
memset (&dr, 0, sizeof (dr));
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
dr.h_contract = h_contract;
@ -1395,7 +1498,6 @@ interpreter_run (void *cls,
GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
&dr.purpose,
&coin_sig.eddsa_signature));
}
cmd->details.deposit.dh
= TALER_MINT_deposit (mint,
@ -1454,7 +1556,7 @@ interpreter_run (void *cls,
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
melt_privs[i] = ref->details.withdraw_sign.coin_priv;
melt_privs[i] = ref->details.reserve_withdraw.coin_priv;
if (GNUNET_OK !=
TALER_string_to_amount (md->amount,
&melt_amounts[i]))
@ -1466,8 +1568,8 @@ interpreter_run (void *cls,
fail (is);
return;
}
melt_sigs[i] = ref->details.withdraw_sign.sig;
melt_pks[i] = *ref->details.withdraw_sign.pk;
melt_sigs[i] = ref->details.reserve_withdraw.sig;
melt_pks[i] = *ref->details.reserve_withdraw.pk;
}
for (i=0;i<num_fresh_coins;i++)
{
@ -1477,7 +1579,7 @@ interpreter_run (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
cmd->details.withdraw_sign.amount,
cmd->details.reserve_withdraw.amount,
is->ip);
fail (is);
return;
@ -1544,7 +1646,7 @@ interpreter_run (void *cls,
/* find melt command */
ref = find_command (is,
ref->details.refresh_reveal.melt_ref);
/* find withdraw_sign command */
/* find reserve_withdraw command */
{
unsigned int idx;
const struct MeltDetails *md;
@ -1563,7 +1665,7 @@ interpreter_run (void *cls,
/* finally, use private key from withdraw sign command */
cmd->details.refresh_link.rlh
= TALER_MINT_refresh_link (mint,
&ref->details.withdraw_sign.coin_priv,
&ref->details.reserve_withdraw.coin_priv,
&link_cb,
is);
if (NULL == cmd->details.refresh_link.rlh)
@ -1574,6 +1676,12 @@ interpreter_run (void *cls,
}
trigger_context_task ();
return;
case OC_WIRE:
cmd->details.wire.wh = TALER_MINT_wire (mint,
&wire_cb,
is);
trigger_context_task ();
return;
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unknown instruction %d at %u (%s)\n",
@ -1623,35 +1731,35 @@ do_shutdown (void *cls,
}
break;
case OC_WITHDRAW_STATUS:
if (NULL != cmd->details.withdraw_status.wsh)
if (NULL != cmd->details.reserve_status.wsh)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command %u (%s) did not complete\n",
i,
cmd->label);
TALER_MINT_withdraw_status_cancel (cmd->details.withdraw_status.wsh);
cmd->details.withdraw_status.wsh = NULL;
TALER_MINT_reserve_status_cancel (cmd->details.reserve_status.wsh);
cmd->details.reserve_status.wsh = NULL;
}
break;
case OC_WITHDRAW_SIGN:
if (NULL != cmd->details.withdraw_sign.wsh)
if (NULL != cmd->details.reserve_withdraw.wsh)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command %u (%s) did not complete\n",
i,
cmd->label);
TALER_MINT_withdraw_sign_cancel (cmd->details.withdraw_sign.wsh);
cmd->details.withdraw_sign.wsh = NULL;
TALER_MINT_reserve_withdraw_cancel (cmd->details.reserve_withdraw.wsh);
cmd->details.reserve_withdraw.wsh = NULL;
}
if (NULL != cmd->details.withdraw_sign.sig.rsa_signature)
if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
{
GNUNET_CRYPTO_rsa_signature_free (cmd->details.withdraw_sign.sig.rsa_signature);
cmd->details.withdraw_sign.sig.rsa_signature = NULL;
GNUNET_CRYPTO_rsa_signature_free (cmd->details.reserve_withdraw.sig.rsa_signature);
cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
}
if (NULL != cmd->details.withdraw_sign.blinding_key.rsa_blinding_key)
if (NULL != cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key)
{
GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.withdraw_sign.blinding_key.rsa_blinding_key);
cmd->details.withdraw_sign.blinding_key.rsa_blinding_key = NULL;
GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key);
cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key = NULL;
}
break;
case OC_DEPOSIT:
@ -1714,6 +1822,13 @@ do_shutdown (void *cls,
cmd->details.refresh_link.rlh = NULL;
}
break;
case OC_WIRE:
if (NULL != cmd->details.wire.wh)
{
TALER_MINT_wire_cancel (cmd->details.wire.wh);
cmd->details.wire.wh = NULL;
}
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unknown instruction %d at %u (%s)\n",
@ -1880,6 +1995,28 @@ run (void *cls,
};
static struct Command commands[] =
{
/* *************** start of /wire testing ************** */
#if WIRE_TEST
{ .oc = OC_WIRE,
.label = "wire-test",
/* /wire/test replies with a 302 redirect */
.expected_response_code = MHD_HTTP_FOUND,
.details.wire.format = "test" },
#endif
#if WIRE_SEPA
{ .oc = OC_WIRE,
.label = "wire-sepa",
/* /wire/sepa replies with a 200 redirect */
.expected_response_code = MHD_HTTP_OK,
.details.wire.format = "sepa" },
#endif
/* *************** end of /wire testing ************** */
#if WIRE_TEST
/* None of this works if 'test' is not allowed as we do
/admin/add/incoming with format 'test' */
/* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
{ .oc = OC_ADMIN_ADD_INCOMING,
.label = "create-reserve-1",
@ -1890,15 +2027,15 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-1",
.expected_response_code = MHD_HTTP_OK,
.details.withdraw_sign.reserve_reference = "create-reserve-1",
.details.withdraw_sign.amount = "EUR:5" },
.details.reserve_withdraw.reserve_reference = "create-reserve-1",
.details.reserve_withdraw.amount = "EUR:5" },
/* Check that deposit and withdraw operation are in history, and
that the balance is now at zero */
{ .oc = OC_WITHDRAW_STATUS,
.label = "withdraw-status-1",
.expected_response_code = MHD_HTTP_OK,
.details.withdraw_status.reserve_reference = "create-reserve-1",
.details.withdraw_status.expected_balance = "EUR:0" },
.details.reserve_status.reserve_reference = "create-reserve-1",
.details.reserve_status.expected_balance = "EUR:0" },
/* Try to deposit the 5 EUR coin (in full) */
{ .oc = OC_DEPOSIT,
.label = "deposit-simple",
@ -1913,8 +2050,8 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-2",
.expected_response_code = MHD_HTTP_PAYMENT_REQUIRED,
.details.withdraw_sign.reserve_reference = "create-reserve-1",
.details.withdraw_sign.amount = "EUR:5" },
.details.reserve_withdraw.reserve_reference = "create-reserve-1",
.details.reserve_withdraw.amount = "EUR:5" },
/* Try to double-spend the 5 EUR coin with different wire details */
{ .oc = OC_DEPOSIT,
@ -1958,8 +2095,8 @@ run (void *cls,
{ .oc = OC_WITHDRAW_SIGN,
.label = "refresh-withdraw-coin-1",
.expected_response_code = MHD_HTTP_OK,
.details.withdraw_sign.reserve_reference = "refresh-create-reserve-1",
.details.withdraw_sign.amount = "EUR:5" },
.details.reserve_withdraw.reserve_reference = "refresh-create-reserve-1",
.details.reserve_withdraw.amount = "EUR:5" },
/* Try to partially spend (deposit) 1 EUR of the 5 EUR coin (in full)
(merchant would receive EUR:0.99 due to 1 ct deposit fee) */
{ .oc = OC_DEPOSIT,
@ -2024,10 +2161,10 @@ run (void *cls,
.details.refresh_melt.melted_coins = melt_coins_1,
.details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
// FIXME: also test with coin that was already melted
// FIXME: also test with coin that was already melted
// (signature differs from coin that was deposited...)
/* *************** end of /refresh testing ************** */
#endif
{ .oc = OC_END }
};

View File

@ -7,6 +7,7 @@ if USE_COVERAGE
endif
bin_PROGRAMS = \
taler-auditor-sign \
taler-mint-keyup \
taler-mint-keycheck \
taler-mint-reservemod \
@ -15,7 +16,6 @@ bin_PROGRAMS = \
taler_mint_keyup_SOURCES = \
taler-mint-keyup.c
taler_mint_keyup_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
@ -24,6 +24,14 @@ taler_mint_keyup_LDADD = \
-lgnunetutil $(XLIB)
taler_mint_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS)
taler_auditor_sign_SOURCES = \
taler-auditor-sign.c
taler_auditor_sign_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/mintdb/libtalermintdb.la \
-lgnunetutil $(XLIB)
taler_mint_sepa_SOURCES = \
taler-mint-sepa.c

View File

@ -23,6 +23,11 @@
#include "taler_mintdb_lib.h"
/**
* Are we running in verbose mode?
*/
static int verbose;
/**
* Filename of the auditor's private key.
*/
@ -44,17 +49,68 @@ static char *mint_request_file;
*/
static char *output_file;
/**
* Handle to the auditor's configuration
*/
static struct GNUNET_CONFIGURATION_Handle *kcfg;
/**
* Master public key of the mint.
*/
static struct TALER_MasterPublicKeyP master_public_key;
/**
* Print denomination key details for diagnostics.
*
* @param dk denomination key to print
*/
static void
print_dk (const struct TALER_DenominationKeyValidityPS *dk)
{
struct TALER_Amount a;
char *s;
fprintf (stdout,
"Denomination key hash: %s\n",
GNUNET_h2s_full (&dk->denom_hash));
TALER_amount_ntoh (&a,
&dk->value);
fprintf (stdout,
"Value: %s\n",
s = TALER_amount_to_string (&a));
GNUNET_free (s);
TALER_amount_ntoh (&a,
&dk->fee_withdraw);
fprintf (stdout,
"Withdraw fee: %s\n",
s = TALER_amount_to_string (&a));
GNUNET_free (s);
TALER_amount_ntoh (&a,
&dk->fee_deposit);
fprintf (stdout,
"Deposit fee: %s\n",
s = TALER_amount_to_string (&a));
GNUNET_free (s);
TALER_amount_ntoh (&a,
&dk->fee_refresh);
fprintf (stdout,
"Refresh fee: %s\n",
s = TALER_amount_to_string (&a));
GNUNET_free (s);
fprintf (stdout,
"Validity start time: %s\n",
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->start)));
fprintf (stdout,
"Withdraw end time: %s\n",
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_withdraw)));
fprintf (stdout,
"Deposit end time: %s\n",
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_spend)));
fprintf (stdout,
"Legal dispute end time: %s\n",
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (dk->expire_legal)));
fprintf (stdout,
"\n");
}
/**
* The main function of the taler-auditor-sign tool. This tool is used
@ -79,18 +135,24 @@ main (int argc,
"public key of the mint (Crockford base32 encoded)", 1,
&GNUNET_GETOPT_set_filename, &mint_public_key},
{'r', "mint-request", "FILE",
"set of keys the mint requested the auditor to sign", 0,
"set of keys the mint requested the auditor to sign", 1,
&GNUNET_GETOPT_set_string, &mint_request_file},
{'o', "output", "FILE",
"where to write our signature", 0,
"where to write our signature", 1,
&GNUNET_GETOPT_set_string, &output_file},
GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION),
GNUNET_GETOPT_OPTION_VERBOSE (&verbose),
GNUNET_GETOPT_OPTION_END
};
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
struct TALER_AuditorSignatureP *sigs;
struct TALER_AuditorPublicKeyP apub;
struct GNUNET_DISK_FileHandle *fh;
struct GNUNET_DISK_FileHandle *fout;
struct TALER_DenominationKeyValidityPS *dks;
unsigned int dks_len;
struct TALER_MintKeyValidityPS kv;
off_t in_size;
unsigned int i;
GNUNET_assert (GNUNET_OK ==
GNUNET_log_setup ("taler-mint-keyup",
@ -114,10 +176,13 @@ main (int argc,
auditor_key_file);
return 1;
}
GNUNET_CRYPTO_eddsa_key_get_public (eddsa_priv,
&apub.eddsa_pub);
if (NULL == mint_public_key)
{
fprintf (stderr,
"Mint public key not given\n");
GNUNET_free (eddsa_priv);
return 1;
}
if (GNUNET_OK !=
@ -129,12 +194,14 @@ main (int argc,
fprintf (stderr,
"Public key `%s' malformed\n",
mint_public_key);
GNUNET_free (eddsa_priv);
return 1;
}
if (NULL == mint_request_file)
{
fprintf (stderr,
"Mint signing request not given\n");
GNUNET_free (eddsa_priv);
return 1;
}
fh = GNUNET_DISK_file_open (mint_request_file,
@ -146,6 +213,7 @@ main (int argc,
"Failed to open file `%s': %s\n",
mint_request_file,
STRERROR (errno));
GNUNET_free (eddsa_priv);
return 1;
}
if (GNUNET_OK !=
@ -157,34 +225,95 @@ main (int argc,
mint_request_file,
STRERROR (errno));
GNUNET_DISK_file_close (fh);
GNUNET_free (eddsa_priv);
return 1;
}
if (0 != (in_size % sizeof (struct TALER_DenominationKeyValidityPS)))
{
fprintf (stderr,
"Input file size of file `%s' is invalid\n",
mint_request_file);
GNUNET_DISK_file_close (fh);
GNUNET_free (eddsa_priv);
return 1;
}
dks_len = in_size / sizeof (struct TALER_DenominationKeyValidityPS);
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
kv.master = master_public_key;
dks = GNUNET_new_array (dks_len,
struct TALER_DenominationKeyValidityPS);
sigs = GNUNET_new_array (dks_len,
struct TALER_AuditorSignatureP);
if (in_size !=
GNUNET_DISK_file_read (fh,
dks,
in_size))
{
fprintf (stderr,
"Failed to read input file `%s': %s\n",
mint_request_file,
STRERROR (errno));
GNUNET_DISK_file_close (fh);
GNUNET_free (sigs);
GNUNET_free (dks);
GNUNET_free (eddsa_priv);
return 1;
}
GNUNET_DISK_file_close (fh);
for (i=0;i<dks_len;i++)
{
struct TALER_DenominationKeyValidityPS *dk = &dks[i];
if (verbose)
print_dk (dk);
kv.start = dk->start;
kv.expire_withdraw = dk->expire_withdraw;
kv.expire_spend = dk->expire_spend;
kv.expire_legal = dk->expire_legal;
kv.value = dk->value;
kv.fee_withdraw = dk->fee_withdraw;
kv.fee_deposit = dk->fee_deposit;
kv.fee_refresh = dk->fee_refresh;
kv.denom_hash = dk->denom_hash;
/* Finally sign ... */
GNUNET_CRYPTO_eddsa_sign (eddsa_priv,
&kv.purpose,
&sigs[i].eddsa_sig);
}
if (NULL == output_file)
{
fprintf (stderr,
"Output file not given\n");
GNUNET_DISK_file_close (fh);
GNUNET_free (dks);
GNUNET_free (sigs);
GNUNET_free (eddsa_priv);
return 1;
}
fout = GNUNET_DISK_file_open (output_file,
GNUNET_DISK_OPEN_READ |
GNUNET_DISK_OPEN_TRUNCATE |
GNUNET_DISK_OPEN_CREATE,
GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE |
GNUNET_DISK_PERM_GROUP_READ |
GNUNET_DISK_PERM_OTHER_READ);
if (NULL == fout)
/* write result to disk */
if (GNUNET_OK !=
TALER_MINTDB_auditor_write (output_file,
&apub,
sigs,
&master_public_key,
dks_len,
dks))
{
fprintf (stderr,
"Failed to open file `%s': %s\n",
"Failed to write to file `%s': %s\n",
output_file,
STRERROR (errno));
GNUNET_DISK_file_close (fh);
GNUNET_free (sigs);
GNUNET_free (dks);
return 1;
}
/* FIXME: finally do real work... */
GNUNET_free (sigs);
GNUNET_free (dks);
GNUNET_free (eddsa_priv);
return 0;
}

View File

@ -157,6 +157,17 @@ struct CoinTypeParams
*/
static char *masterkeyfile;
/**
* Filename where to write denomination key signing
* requests for the auditor (optional, can be NULL).
*/
static char *auditorrequestfile;
/**
* Handle for writing the output for the auditor.
*/
static FILE *auditor_output_file;
/**
* Director of the mint, containing the keys.
*/
@ -807,6 +818,20 @@ mint_keys_update_cointype (void *cls,
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
return;
}
if ( (NULL != auditor_output_file) &&
(sizeof (denomkey_issue.issue.properties) !=
fwrite (&denomkey_issue.issue.properties,
sizeof (struct TALER_DenominationKeyValidityPS),
1,
auditor_output_file)) )
{
fprintf (stderr,
"Failed to write denomination key information to %s: %s\n",
auditorrequestfile,
STRERROR (errno));
*ret = GNUNET_SYSERR;
return;
}
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
p.anchor = GNUNET_TIME_absolute_add (p.anchor,
p.duration_spend);
@ -859,6 +884,9 @@ main (int argc,
{'m', "master-key", "FILE",
"master key file (private key)", 1,
&GNUNET_GETOPT_set_filename, &masterkeyfile},
{'o', "output", "FILE",
"auditor denomination key signing request file to create", 1,
&GNUNET_GETOPT_set_filename, &auditorrequestfile},
{'t', "time", "TIMESTAMP",
"pretend it is a different time for the update", 0,
&GNUNET_GETOPT_set_string, &pretend_time_str},
@ -927,6 +955,20 @@ main (int argc,
GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv,
&master_public_key.eddsa_pub);
if (NULL != auditorrequestfile)
{
auditor_output_file = FOPEN (auditorrequestfile,
"w");
if (NULL == auditor_output_file)
{
fprintf (stderr,
"Failed to open `%s' for writing: %s\n",
auditorrequestfile,
STRERROR (errno));
return 1;
}
}
/* check if key from file matches the one from the configuration */
{
struct GNUNET_CRYPTO_EddsaPublicKey master_public_key_from_cfg;
@ -986,6 +1028,11 @@ main (int argc,
if (GNUNET_OK != mint_keys_update_denomkeys ())
return 1;
if (NULL != auditor_output_file)
{
FCLOSE (auditor_output_file);
auditor_output_file = NULL;
}
return 0;
}

View File

@ -18,7 +18,7 @@ taler_mint_httpd_SOURCES = \
taler-mint-httpd_mhd.c taler-mint-httpd_mhd.h \
taler-mint-httpd_admin.c taler-mint-httpd_admin.h \
taler-mint-httpd_deposit.c taler-mint-httpd_deposit.h \
taler-mint-httpd_withdraw.c taler-mint-httpd_withdraw.h \
taler-mint-httpd_reserve.c taler-mint-httpd_reserve.h \
taler-mint-httpd_wire.c taler-mint-httpd_wire.h \
taler-mint-httpd_refresh.c taler-mint-httpd_refresh.h
taler_mint_httpd_LDADD = \
@ -34,3 +34,9 @@ if HAVE_DEVELOPER
taler_mint_httpd_SOURCES += \
taler-mint-httpd_test.c taler-mint-httpd_test.h
endif
check_SCRIPTS = \
test_taler_mint_httpd.sh \
test_taler_mint_httpd_afl.sh
TESTS = $(check_SCRIPTS)

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,8 @@
POST /deposit HTTP/1.1
Host: locst:8081
Accept: */*
Content-: applicn/json
Content-Length: 1658
Expect: 100-continue
{"ub_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26E9M8S0M6CSH6X334GSN8RW30D9G8MT46CA660W34GSG6MT4AD9K8GT3ECSH6MVK0E2374V38H1M8MR4CDJ66MWK4E1S6MR3GCT28CV32H1Q8N23GCHG70S36C1K8MS3GCSN8RV36D9S710KGD9K6GWKEGJ28GRM4CJ56X1K6DJ18D2KGHA46D13GDA66GVK4GHJ8N13AE9J8RVK6GT184S48E1K6X336G9Q8N142CJ4692M6EA16GRKJD9N6523ADA36X13GG9G70TK6DHN68R36CT18GR4CDSJ6CW3GCT364W46CSR8RV42GJ474SMADSH851K4H9Q8GS42CHS8RV3GCSJ64V46DSN8RSM6HHN6N246D9S6934AH9P6X23JGSH652K0DJ5612KJGA26N242CH35452081918G2J2G0","timestamp":"/Date(1442821652)/","f":{"currency":"EUR","value":5,"fraction":0},"wire":{"type":"TEST","bank":"dest bank","account":42},"coin_pub":"JXWK4NS0H2W4V4BETQ90CCEDADP6QQ3MV3YZ7RV2KXEM8PWXE8Q0","H_wire":"YQED9FDYPKK2QQYB3FS19Y15ZMKBAXJP2C73CXASAF1KM6ZYY723TEJ3HBR6D864A7X5W58G92QJ0A9PFMZNB81ZP9NJAQQCCABM4RG","H_contract":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","transaction_id":1,"refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
GET /keys HTTP/1.1
User-Agent: Wget/1.16.3 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: 127.0.0.1:8081
Connection: Keep-Alive

View File

@ -0,0 +1,5 @@
GET /refresh/link?coin_pub=WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
POST /refresh/reveal HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 255
{"session_hash":"V97SB8T670M9V71D1Q0KVQ4GSJCVQ5AAKTTH9QKT0ZJZZBFNZAV4NA8NMWRRGVPFEBEGB6ANCN9BPQASJ40TM4Y1C49648TJJ07PGSG","transfer_privs":[["EQKJA401A9NJ2YJDFZJ1EV8AYXBHWZB6NT5T0TWSJHVKVDM6W8A0"],["TKDJ4DF3GZVG0DGAB9E3RGBGSTANYB6JVVWXJGPMB2AY4VQNTBA0"]]}

View File

@ -0,0 +1,4 @@
GET /reserve/status?reserve_pub=TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0 HTTP/1.1
Host: localhost:8081
Accept: */*

View File

@ -0,0 +1,7 @@
POST /reserve/withdraw HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 919
{"coin_ev":"Q5X8A8TCBFH7E5BMY7HSB17SHFTM1JPJGV61P2CA7Z9EXG8P2HYS69B31NZESKXHSZHNJ2DQN3CC2AWFNC6V90J577JD3TXBMAY8Y5M9V60KKT73Z1DW24JFSNAK91G1F2WT55ADP1EG7N5F9AY7A7ZJD03MPYSH0RDP7SVZS2KRPA5JRHFR4GDJ59CFNE7A43M95ZKQHQAS8","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","reserve_sig":"8427B3RTB217124EB1C37ZVJFC08KN17RHGHE9ENZQMQVJ0S11SAX6H8Z06SWCKT06DRQ9DQ8XD786XKQ94T27PYR9GC9EMT1Y02W10"}

View File

@ -0,0 +1,5 @@
GET /wire HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -0,0 +1,5 @@
GET /wire/sepa HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -0,0 +1,5 @@
GET /wire/test HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json

View File

@ -0,0 +1,7 @@
PoST /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POsT /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POSt /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST ¯admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST ¯admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST ?admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /adMin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin?add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST 'admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/aDd/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /aDmin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/atd/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admIn/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin?add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incOming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/Add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incmming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/aDd/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incomIng HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/iNcoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incominG HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incomiNg HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming @TTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HtTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HDTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HVTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTÔP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTDP/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HT\P/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTT@/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTÐ/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/±.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTT@/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/q.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTT/1.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/9.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/0.1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1&1
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.±
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.3
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

View File

@ -0,0 +1,7 @@
POST /admin/add/incoming HTTP/1.!
Host: localhost:8081
Accept: */*
Content-Type: application/json
Content-Length: 220
{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}}

Some files were not shown because too many files have changed in this diff Show More