diff options
-rw-r--r-- | m4/libcurl.m4 | 251 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 8 | ||||
-rw-r--r-- | src/lib/merchant_api_context.h | 2 | ||||
-rw-r--r-- | src/lib/merchant_api_json.h | 2 | ||||
-rw-r--r-- | src/lib/merchant_api_pay.c | 105 |
5 files changed, 339 insertions, 29 deletions
diff --git a/m4/libcurl.m4 b/m4/libcurl.m4 new file mode 100644 index 00000000..a84077a5 --- /dev/null +++ b/m4/libcurl.m4 @@ -0,0 +1,251 @@ +# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], +# [ACTION-IF-YES], [ACTION-IF-NO]) +# ---------------------------------------------------------- +# David Shaw <dshaw@jabberwocky.com> May-09-2006 +# +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. +# +# This macro #defines HAVE_LIBCURL if a working libcurl setup is +# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary +# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are +# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy +# where yyy are the various protocols supported by libcurl. Both xxx +# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of +# the macro for the complete list of possible defines. Shell +# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also +# defined to 'yes' for those features and protocols that were found. +# Note that xxx and yyy keep the same capitalization as in the +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only guess what protocols are available, +# or use curl_version_info to figure it out at runtime. + +AC_DEFUN([LIBCURL_CHECK_CONFIG], +[ + AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) + AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) + AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) + AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) + AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) + AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) + AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) + AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) + + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) + AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3]) + AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) + + AC_ARG_WITH(libcurl, + AC_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), + [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) + + if test "$_libcurl_with" != "no" ; then + + AC_PROG_AWK + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + AC_PATH_PROG([_libcurl_config],[curl-config],[], + ["$withval/bin"]) + else + AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) + fi + + if test x$_libcurl_config != "x" ; then + AC_CACHE_CHECK([for the version of libcurl], + [libcurl_cv_lib_curl_version], + [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + AC_CACHE_CHECK([for libcurl >= version $2], + [libcurl_cv_lib_version_ok], + [ + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + ]) + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + AC_CACHE_CHECK([whether libcurl is usable], + [libcurl_cv_lib_curl_usable], + [ + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[ +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_WRITEDATA; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +if (x) ; +]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + ]) + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + AC_CHECK_FUNC(curl_free,, + AC_DEFINE(curl_free,free, + [Define curl_free() as free() if our version of curl lacks curl_free.])) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + AC_DEFINE(HAVE_LIBCURL,1, + [Define to 1 if you have a functional curl library.]) + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL) + + for _libcurl_feature in $_libcurl_features ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) + eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 (0x070b00 == 461568) + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + + # RTSP, IMAP, POP3 and SMTP were added in + # 7.20.0 (0x071400 == 463872) + if test $_libcurl_version -ge 463872; then + _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) + eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + ifelse([$4],,:,[$4]) + else + # This is the IF-YES path + ifelse([$3],,:,[$3]) + fi + + unset _libcurl_with +])dnl diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 5b612f73..8c9957c3 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -21,7 +21,7 @@ #ifndef _TALER_MERCHANT_SERVICE_H #define _TALER_MERCHANT_SERVICE_H -#include "taler_util.h" +#include <taler/taler_util.h> /* ********************* event loop *********************** */ @@ -171,6 +171,7 @@ struct TALER_MERCHANT_PayCoin * Pay a merchant. API for wallets that have the coin's private keys. * * @param merchant the merchant context + * @param mint_uri URI of the mint that the coins belong to * @param h_wire hash of the merchant’s account details * @param h_contract hash of the contact of the merchant with the customer * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant @@ -186,6 +187,7 @@ struct TALER_MERCHANT_PayCoin */ struct TALER_MERCHANT_Pay * TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, + const char *mint_uri, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, struct GNUNET_TIME_Absolute timestamp, @@ -193,7 +195,7 @@ TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, const struct TALER_MerchantPublicKeyP *merchant_pub, struct GNUNET_TIME_Absolute refund_deadline, unsigned int num_coins, - const struct TLAER_MERCHANT_PayCoin *coins, + const struct TALER_MERCHANT_PayCoin *coins, TALER_MERCHANT_PayCallback pay_cb, void *pay_cb_cls); @@ -244,6 +246,7 @@ struct TALER_MERCHANT_PaidCoin * in the type of @a coins compared to #TALER_MERCHANT_pay(). * * @param merchant the merchant context + * @param mint_uri URI of the mint that the coins belong to * @param h_wire hash of the merchant’s account details * @param h_contract hash of the contact of the merchant with the customer * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant @@ -259,6 +262,7 @@ struct TALER_MERCHANT_PaidCoin */ struct TALER_MERCHANT_Pay * TALER_MERCHANT_pay_frontend (struct TALER_MERCHANT_Context *merchant, + const char *mint_uri, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, struct GNUNET_TIME_Absolute timestamp, diff --git a/src/lib/merchant_api_context.h b/src/lib/merchant_api_context.h index 6a8d7a28..e54d34cc 100644 --- a/src/lib/merchant_api_context.h +++ b/src/lib/merchant_api_context.h @@ -24,7 +24,7 @@ #include <curl/curl.h> #include <gnunet/gnunet_util_lib.h> #include "taler_merchant_service.h" -#include "taler_signatures.h" +#include <taler/taler_signatures.h> /** diff --git a/src/lib/merchant_api_json.h b/src/lib/merchant_api_json.h index 9f7b0812..5f5265cf 100644 --- a/src/lib/merchant_api_json.h +++ b/src/lib/merchant_api_json.h @@ -22,7 +22,7 @@ */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> -#include "taler_util.h" +#include <taler/taler_util.h> #include <jansson.h> diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c index 13715f85..e33da423 100644 --- a/src/lib/merchant_api_pay.c +++ b/src/lib/merchant_api_pay.c @@ -27,7 +27,7 @@ #include "taler_merchant_service.h" #include "merchant_api_json.h" #include "merchant_api_context.h" -#include "taler_signatures.h" +#include <taler/taler_signatures.h> /** @@ -74,14 +74,14 @@ struct TALER_MERCHANT_Pay * Function called when we're done processing the * HTTP /pay request. * - * @param cls the `struct TALER_MERCHANT_PayHandle` + * @param cls the `struct TALER_MERCHANT_Pay` * @param eh the curl request handle */ static void handle_pay_finished (void *cls, CURL *eh) { - struct TALER_MERCHANT_PayHandle *ph = cls; + struct TALER_MERCHANT_Pay *ph = cls; long response_code; json_t *json; @@ -135,6 +135,7 @@ handle_pay_finished (void *cls, * Pay a merchant. API for wallets that have the coin's private keys. * * @param merchant the merchant context + * @param mint_uri URI of the mint that the coins belong to * @param h_wire hash of the merchant’s account details * @param h_contract hash of the contact of the merchant with the customer * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant @@ -150,6 +151,7 @@ handle_pay_finished (void *cls, */ struct TALER_MERCHANT_Pay * TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, + const char *mint_uri, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, struct GNUNET_TIME_Absolute timestamp, @@ -161,40 +163,91 @@ TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, TALER_MERCHANT_PayCallback pay_cb, void *pay_cb_cls) { - struct TALER_MERCHANT_PayHandle *ph; + struct TALER_MERCHANT_Pay *ph; json_t *pay_obj; + json_t *j_coins; CURL *eh; struct GNUNET_HashCode h_wire; struct TALER_Amount amount_without_fee; + unsigned int i; + struct TALER_DepositRequestPS dr; + + dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); + dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); + dr.h_contract = *h_contract; + dr.h_wire = *h_wire; + dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); + dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); + dr.transaction_id = GNUNET_htonll (transaction_id); + dr.merchant = *merchant_pub; + j_coins = json_array (); + for (i=0;i<num_coins;i++) + { + json_t *j_coin; + const struct TALER_MERCHANT_PayCoin *pc = &coins[i]; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_Amount fee; + + /* prepare 'dr' for this coin to generate coin signature */ + GNUNET_CRYPTO_ecdhe_key_get_public (&pc->coin_priv.edche_priv, + &dr.coin_pub.ecdhe_pub); + TALER_amount_hton (&dr.amount_with_fee, + &pc->amount_with_fee); + if (GNUNET_SYSERR == + TALER_amount_subtract (&fee, + &pc->amount_with_fee, + &pc->fee)) + { + /* Integer underflow, fee larger than total amount? + This should not happen (client violated API!) */ + GNUNET_break (0); + json_decref (j_coins); + return NULL; + } + TALER_amount_hton (&dr.deposit_fee, + &fee); + GNUNET_CRYPTO_eddsa_sign (&pc->coin_priv.eddsa_priv, + &dr.purpose, + &coin_sig.eddsa_sig); + + /* create JSON for this coin */ + j_coin = json_pack ("{s:o, s:o," /* f/coin_pub */ + " s:o, s:o," /* denom_pub / ub_sig */ + " s:o}", /* coin_sig */ + "f", TALER_json_from_amount (&pc->amount_with_fee), + "coin_pub", TALER_json_from_data (&dr.coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP)), + "denom_pub", TALER_json_from_rsa_public_key (pc->denom_pub.rsa_public_key), + "ub_sig", TALER_json_from_rsa_signature (pc->denom_sig.rsa_signature), + "coin_sig", TALER_json_from_data (&coin_sig, + sizeof (coin_sig)) + ); + json_array_append (j_coins, + j_coin); + } + - pay_obj = json_pack ("{s:o, s:O," /* f/wire */ - " s:o, s:o," /* H_wire, H_contract */ - " s:o, s:o," /* coin_pub, denom_pub */ - " s:o, s:o," /* ub_sig, timestamp */ - " s:I, s:o," /* transaction id, merchant_pub */ - " s:o, s:o," /* refund_deadline, wire_deadline */ - " s:o}", /* coin_sig */ - "f", TALER_json_from_amount (amount), - "wire", wire_details, + pay_obj = json_pack ("{s:o, s:o," /* H_wire/H_contract */ + " s:I, s:o," /* transaction id, timestamp */ + " s:o, s:s," /* refund_deadline, mint */ + " s:o, s:o," /* coins, max_fee */ + " s:o}", /* amount */ "H_wire", TALER_json_from_data (&h_wire, sizeof (h_wire)), "H_contract", TALER_json_from_data (h_contract, sizeof (struct GNUNET_HashCode)), - "coin_pub", TALER_json_from_data (coin_pub, - sizeof (*coin_pub)), - "denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key), - "ub_sig", TALER_json_from_rsa_signature (denom_sig->rsa_signature), - "timestamp", TALER_json_from_abs (timestamp), "transaction_id", (json_int_t) transaction_id, - "merchant_pub", TALER_json_from_data (merchant_pub, - sizeof (*merchant_pub)), + "timestamp", TALER_json_from_abs (timestamp), "refund_deadline", TALER_json_from_abs (refund_deadline), - "edate", TALER_json_from_abs (wire_deadline), - "coin_sig", TALER_json_from_data (coin_sig, - sizeof (*coin_sig)) + "mint", mint_uri, + "coins", j_coins, + "max_fee", TALER_json_from_amount (max_fee), + "amount", TALER_json_from_amount (amount) ); - ph = GNUNET_new (struct TALER_MERCHANT_PayHandle); + // optionally: add edate! "edate", TALER_json_from_abs (wire_deadline), + + ph = GNUNET_new (struct TALER_MERCHANT_Pay); #if 0 ph->merchant = merchant; ph->cb = cb; @@ -262,6 +315,7 @@ TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, * in the type of @a coins compared to #TALER_MERCHANT_pay(). * * @param merchant the merchant context + * @param mint_uri URI of the mint that the coins belong to * @param h_wire hash of the merchant’s account details * @param h_contract hash of the contact of the merchant with the customer * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant @@ -277,6 +331,7 @@ TALER_MERCHANT_pay_wallet (struct TALER_MERCHANT_Context *merchant, */ struct TALER_MERCHANT_Pay * TALER_MERCHANT_pay_frontend (struct TALER_MERCHANT_Context *merchant, + const char *mint_uri, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, struct GNUNET_TIME_Absolute timestamp, @@ -300,7 +355,7 @@ TALER_MERCHANT_pay_frontend (struct TALER_MERCHANT_Context *merchant, * @param pay the pay permission request handle */ void -TALER_MERCHANT_pay_cancel (struct TALER_MERCHANT_PayHandle *pay) +TALER_MERCHANT_pay_cancel (struct TALER_MERCHANT_Pay *pay) { if (NULL != pay->job) { |