diff options
| author | Christian Grothoff <christian@grothoff.org> | 2020-01-19 20:33:07 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2020-01-19 20:33:07 +0100 | 
| commit | 59398cfd76ed01df0ba5f33022727047afd6b270 (patch) | |
| tree | 0da425ba9a3e0aeaff94d058f653d59f73f46dcc /src | |
| parent | 600592dbf6aced50a92cced8ab9d773d06f0f4f4 (diff) | |
separate util.c and url.c
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/taler_crypto_lib.h | 7 | ||||
| -rw-r--r-- | src/util/Makefile.am | 4 | ||||
| -rw-r--r-- | src/util/amount.c | 5 | ||||
| -rw-r--r-- | src/util/config.c | 57 | ||||
| -rw-r--r-- | src/util/crypto.c | 6 | ||||
| -rw-r--r-- | src/util/crypto_wire.c | 19 | ||||
| -rw-r--r-- | src/util/getopt.c | 87 | ||||
| -rw-r--r-- | src/util/os_installation.c | 3 | ||||
| -rw-r--r-- | src/util/payto.c | 85 | ||||
| -rw-r--r-- | src/util/url.c | 409 | ||||
| -rw-r--r-- | src/util/util.c | 548 | 
11 files changed, 662 insertions, 568 deletions
| diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 3fd72723..206a3db3 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -739,7 +739,7 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,  /**   * Compute the hash of the given wire details.   The resulting - * hash is what is put into the contract. + * hash is what is signed by the master key.   *   * @param payto_uri bank account   * @param[out] hc set to the hash @@ -750,7 +750,7 @@ TALER_exchange_wire_signature_hash (const char *payto_uri,  /** - * Check the signature in @a wire_s. + * Check the signature in @a master_sig.   *   * @param payto_uri URL that is signed   * @param master_pub master public key of the exchange @@ -781,7 +781,8 @@ TALER_exchange_wire_signature_make (const char *payto_uri,  /**   * Compute the hash of the given wire details.   The resulting - * hash is what is put into the contract. + * @a hc is what will be put into the contract between customer + * and merchant for signing by both parties.   *   * @param payto_uri bank account   * @param salt salt used to eliminate brute-force inversion diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 74e61ccd..95cc233a 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -24,8 +24,12 @@ lib_LTLIBRARIES = \  libtalerutil_la_SOURCES = \    amount.c \ +  config.c \    crypto.c \    crypto_wire.c \ +  getopt.c \ +  payto.c \ +  url.c \    util.c \    os_installation.c diff --git a/src/util/amount.c b/src/util/amount.c index a9b41ba7..d5789c1d 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -22,12 +22,7 @@   * @author Christian Grothoff   */  #include "platform.h" -#if HAVE_GNUNET_GNUNET_UTIL_LIB_H  #include "taler_util.h" -#elif HAVE_GNUNET_GNUNET_UTIL_TALER_WALLET_LIB_H -#include "taler_util_wallet.h" -#endif -#include <gcrypt.h>  /**   * Maximum legal 'value' for an amount, based on IEEE double (for JavaScript compatibility). diff --git a/src/util/config.c b/src/util/config.c new file mode 100644 index 00000000..e65a144a --- /dev/null +++ b/src/util/config.c @@ -0,0 +1,57 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2020 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  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, see <http://www.gnu.org/licenses/> +*/ +/** + * @file config.c + * @brief configuration parsing functions for Taler-specific data types + * @author Florian Dold + * @author Benedikt Mueller + */ +#include "platform.h" +#include "taler_util.h" + + +/** + * Obtain denomination amount from configuration file. + * + * @param cfg configuration to use + * @param section section of the configuration to access + * @param option option of the configuration to access + * @param[out] denom set to the amount found in configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +TALER_config_get_denom (const struct GNUNET_CONFIGURATION_Handle *cfg, +                        const char *section, +                        const char *option, +                        struct TALER_Amount *denom) +{ +  char *str; + +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_get_value_string (cfg, +                                             section, +                                             option, +                                             &str)) +    return GNUNET_NO; +  if (GNUNET_OK != TALER_string_to_amount (str, +                                           denom)) +  { +    GNUNET_free (str); +    return GNUNET_SYSERR; +  } +  GNUNET_free (str); +  return GNUNET_OK; +} diff --git a/src/util/crypto.c b/src/util/crypto.c index 9fe08984..e847633f 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -22,13 +22,7 @@   * @author Christian Grothoff   */  #include "platform.h" - -#if HAVE_GNUNET_GNUNET_UTIL_TALER_WALLET_LIB_H -#include "taler_util_wallet.h" -#endif -#if HAVE_GNUNET_GNUNET_UTIL_LIB_H  #include "taler_util.h" -#endif  #include <gcrypt.h> diff --git a/src/util/crypto_wire.c b/src/util/crypto_wire.c index a8941e18..d935bec4 100644 --- a/src/util/crypto_wire.c +++ b/src/util/crypto_wire.c @@ -24,8 +24,8 @@  /** - * Compute the hash of the given wire details.   The resulting - * hash is what is put into the contract. + * Compute the hash of the given wire details. The resulting + * hash is what is signed by the master key.   *   * @param payto_uri bank account   * @param[out] hc set to the hash @@ -46,7 +46,7 @@ TALER_exchange_wire_signature_hash (const char *payto_uri,  /** - * Check the signature in @a wire_s. + * Check the signature in @a master_sig.   *   * @param payto_uri URL that is signed   * @param master_pub master public key of the exchange @@ -101,7 +101,8 @@ TALER_exchange_wire_signature_make (const char *payto_uri,  /**   * Compute the hash of the given wire details.   The resulting - * hash is what is put into the contract. + * @a hc is what will be put into the contract between customer + * and merchant for signing by both parties.   *   * @param payto_uri bank account   * @param salt salt used to eliminate brute-force inversion @@ -126,7 +127,15 @@ TALER_merchant_wire_signature_hash (const char *payto_uri,  /** - * Check the signature in @a merch_sig. (Not yet used anywhere.) + * Check the signature in @a merch_sig. + * (Not yet used anywhere.) + * + * Expected to be used if/when we get @a merch_pub signed via + * X.509 *and* have a way for the WebEx wallet to check that the + * @a merch_pub provided matches that of the X.509 certificate + * from the Web site. Until then, @a merch_pub cannto be + * validated (no PKI), and hence there is no point in checking + * these signatures. (See #5129 and #3946).   *   * @param payto_uri URL that is signed   * @param salt the salt used to salt the @a payto_uri when hashing diff --git a/src/util/getopt.c b/src/util/getopt.c new file mode 100644 index 00000000..b8948bbb --- /dev/null +++ b/src/util/getopt.c @@ -0,0 +1,87 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2020 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  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, see <http://www.gnu.org/licenses/> +*/ +/** + * @file getopt.c + * @brief Helper functions for parsing Taler-specific command-line arguments + * @author Florian Dold + */ +#include "platform.h" +#include "taler_util.h" + + +/** + * Set an option with an amount from the command line.  A pointer to + * this function should be passed as part of the 'struct + * GNUNET_GETOPT_CommandLineOption' array to initialize options of + * this type. + * + * @param ctx command line processing context + * @param scls additional closure (will point to the `struct TALER_Amount`) + * @param option name of the option + * @param value actual value of the option as a string. + * @return #GNUNET_OK if parsing the value worked + */ +static int +set_amount (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, +            void *scls, +            const char *option, +            const char *value) +{ +  struct TALER_Amount *amount = scls; + +  (void) ctx; +  if (GNUNET_OK != +      TALER_string_to_amount (value, +                              amount)) +  { +    fprintf (stderr, +             _ ("Failed to parse amount in option `%s'\n"), +             option); +    return GNUNET_SYSERR; +  } + +  return GNUNET_OK; +} + + +/** + * Allow user to specify an amount on the command line. + * + * @param shortName short name of the option + * @param name long name of the option + * @param argumentHelp help text for the option argument + * @param description long help text for the option + * @param[out] amount set to the amount specified at the command line + */ +struct GNUNET_GETOPT_CommandLineOption +TALER_getopt_get_amount (char shortName, +                         const char *name, +                         const char *argumentHelp, +                         const char *description, +                         struct TALER_Amount *amount) +{ +  struct GNUNET_GETOPT_CommandLineOption clo = { +    .shortName =  shortName, +    .name = name, +    .argumentHelp = argumentHelp, +    .description = description, +    .require_argument = 1, +    .processor = &set_amount, +    .scls = (void *) amount +  }; + +  return clo; +} diff --git a/src/util/os_installation.c b/src/util/os_installation.c index 1fe5ea07..beea5d70 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -1,6 +1,6 @@  /*       This file is part of GNU Taler. -     Copyright (C) 2016 Inria +     Copyright (C) 2016 Taler Systems SA       Taler is free software; you can redistribute it and/or modify       it under the terms of the GNU General Public License as published @@ -17,7 +17,6 @@       Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,       Boston, MA 02110-1301, USA.  */ -  /**   * @file os_installation.c   * @brief initialize libgnunet OS subsystem for Taler. diff --git a/src/util/payto.c b/src/util/payto.c new file mode 100644 index 00000000..484db0bb --- /dev/null +++ b/src/util/payto.c @@ -0,0 +1,85 @@ +/* +  This file is part of TALER +  Copyright (C) 2019-2020 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  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, see <http://www.gnu.org/licenses/> +*/ +/** + * @file payto.c + * @brief Common utility functions for dealing with payto://-URIs + * @author Florian Dold + */ +#include "platform.h" +#include "taler_util.h" + + +/** + * Prefix of PAYTO URLs. + */ +#define PAYTO "payto://" + + +/** + * Obtain the payment method from a @a payto_uri + * + * @param payto_uri the URL to parse + * @return NULL on error (malformed @a payto_uri) + */ +char * +TALER_payto_get_method (const char *payto_uri) +{ +  const char *start; +  const char *end; + +  if (0 != strncmp (payto_uri, +                    PAYTO, +                    strlen (PAYTO))) +    return NULL; +  start = &payto_uri[strlen (PAYTO)]; +  end = strchr (start, +                (unsigned char) '/'); +  if (NULL == end) +    return NULL; +  return GNUNET_strndup (start, +                         end - start); +} + + +/** + * Obtain the account name from a payto URL. + * + * @param payto an x-taler-bank payto URL + * @return only the account name from the @a payto URL, NULL if not an x-taler-bank + *   payto URL + */ +char * +TALER_xtalerbank_account_from_payto (const char *payto) +{ +  const char *beg; +  const char *end; + +  if (0 != strncasecmp (payto, +                        "payto://x-taler-bank/", +                        strlen ("payto://x-taler-bank/"))) +    return NULL; +  beg = strchr (&payto[strlen ("payto://x-taler-bank/")], +                '/'); +  if (NULL == beg) +    return NULL; +  beg++; +  end = strchr (beg, +                '?'); +  if (NULL == end) +    return GNUNET_strdup (beg); +  return GNUNET_strndup (beg, +                         end - beg); +} diff --git a/src/util/url.c b/src/util/url.c new file mode 100644 index 00000000..be15917b --- /dev/null +++ b/src/util/url.c @@ -0,0 +1,409 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2020 Taler Systems SA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  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, see <http://www.gnu.org/licenses/> +*/ +/** + * @file url.c + * @brief URL handling utility functions + * @author Florian Dold + */ +#include "platform.h" +#include "taler_util.h" + + +/** + * Check if a character is reserved and should + * be urlencoded. + * + * @param c character to look at + * @return #GNUNET_YES if @a c needs to be urlencoded, + *         #GNUNET_NO otherwise + */ +static bool +is_reserved (char c) +{ +  switch (c) +  { +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  case 'a': case 'b': case 'c': case 'd': case 'e': +  case 'f': case 'g': case 'h': case 'i': case 'j': +  case 'k': case 'l': case 'm': case 'n': case 'o': +  case 'p': case 'q': case 'r': case 's': case 't': +  case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': +  case 'A': case 'B': case 'C': case 'D': case 'E': +  case 'F': case 'G': case 'H': case 'I': case 'J': +  case 'K': case 'L': case 'M': case 'N': case 'O': +  case 'P': case 'Q': case 'R': case 'S': case 'T': +  case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': +  case '-': case '.': case '_': case '~': +    return GNUNET_NO; +  default: +    break; +  } +  return GNUNET_YES; +} + + +/** + * Get the length of a string after it has been + * urlencoded. + * + * @param s the string + * @returns the size of the urlencoded @a s + */ +static size_t +urlencode_len (const char *s) +{ +  size_t len = 0; +  for (; *s != '\0'; len++, s++) +    if (GNUNET_YES == is_reserved (*s)) +      len += 2; +  return len; +} + + +/** + * URL-encode a string according to rfc3986. + * + * @param buf buffer to write the result to + * @param s string to encode + */ +static void +buffer_write_urlencode (struct GNUNET_Buffer *buf, +                        const char *s) +{ +  GNUNET_buffer_ensure_remaining (buf, urlencode_len (s) + 1); + +  for (size_t i = 0; i < strlen (s); i++) +  { +    if (GNUNET_YES == is_reserved (s[i])) +      GNUNET_buffer_write_fstr (buf, "%%%02X", s[i]); +    else +      buf->mem[buf->position++] = s[i]; +  } +} + + +/** + * URL-encode a string according to rfc3986. + * + * @param s string to encode + * @returns the urlencoded string, the caller must free it with #GNUNET_free() + */ +char * +TALER_urlencode (const char *s) +{ +  struct GNUNET_Buffer buf = { 0 }; + +  buffer_write_urlencode (&buf, s); +  return GNUNET_buffer_reap_str (&buf); +} + + +/** + * Make an absolute URL with query parameters. + * + * @param base_url absolute base URL to use + * @param path path of the url + * @param ... NULL-terminated key-value pairs (char *) for query parameters, + *        the value will be url-encoded + * @returns the URL (must be freed with #GNUNET_free) or + *          NULL if an error occured. + */ +char * +TALER_url_join (const char *base_url, +                const char *path, +                ...) +{ +  unsigned int iparam = 0; +  va_list args; +  struct GNUNET_Buffer buf = { 0 }; +  size_t len; + +  GNUNET_assert (NULL != base_url); +  GNUNET_assert (NULL != path); +  if (0 == strlen (base_url)) +  { +    /* base URL can't be empty */ +    GNUNET_break (0); +    return NULL; +  } +  if ('/' != base_url[strlen (base_url) - 1]) +  { +    /* Must be an actual base URL! */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Base URL `%s' does not end with '/'\n", +                base_url); +    return NULL; +  } +  if ('/' == path[0]) +  { +    /* The path must be relative. */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Path `%s' is not relative\n", +                path); +    return NULL; +  } + +  /* 1st pass: compute length */ +  len = strlen (base_url) + strlen (path) + 1; + +  va_start (args, path); +  while (1) +  { +    char *key; +    char *value; +    key = va_arg (args, char *); +    if (NULL == key) +      break; +    value = va_arg (args, char *); +    if (NULL == value) +      continue; +    len += urlencode_len (value) + strlen (key) + 2; +  } +  va_end (args); + +  GNUNET_buffer_prealloc (&buf, len); +  GNUNET_buffer_write_str (&buf, base_url); +  GNUNET_buffer_write_str (&buf, path); + +  va_start (args, path); +  while (1) +  { +    char *key; +    char *value; + +    key = va_arg (args, char *); +    if (NULL == key) +      break; +    value = va_arg (args, char *); +    if (NULL == value) +      continue; +    GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); +    iparam++; +    GNUNET_buffer_write_str (&buf, key); +    GNUNET_buffer_write_str (&buf, "="); +    buffer_write_urlencode (&buf, value); +  } +  va_end (args); + +  return GNUNET_buffer_reap_str (&buf); +} + + +/** + * Make an absolute URL for the given parameters. + * + * @param proto protocol for the URL (typically https) + * @param host hostname for the URL + * @param prefix prefix for the URL + * @param path path for the URL + * @param args NULL-terminated key-value pairs (char *) for query parameters, + *        the value will be url-encoded + * @returns the URL, must be freed with #GNUNET_free + */ +char * +TALER_url_absolute_raw_va (const char *proto, +                           const char *host, +                           const char *prefix, +                           const char *path, +                           va_list args) +{ +  struct GNUNET_Buffer buf = { 0 }; +  unsigned int iparam = 0; +  size_t len = 0; +  va_list args2; + +  len += strlen (proto) + strlen ("://") + strlen (host); +  len += strlen (prefix) + strlen (path); + +  va_copy (args2, args); +  while (1) +  { +    char *key; +    char *value; +    key = va_arg (args2, char *); +    if (NULL == key) +      break; +    value = va_arg (args2, char *); +    if (NULL == value) +      continue; +    len += urlencode_len (value) + strlen (key) + 2; +  } +  va_end (args2); + +  GNUNET_buffer_prealloc (&buf, len); + +  GNUNET_buffer_write_str (&buf, proto); +  GNUNET_buffer_write_str (&buf, "://"); +  GNUNET_buffer_write_str (&buf, host); + +  GNUNET_buffer_write_path (&buf, prefix); +  GNUNET_buffer_write_path (&buf, path); + +  va_copy (args2, args); +  while (1) +  { +    char *key; +    char *value; +    key = va_arg (args, char *); +    if (NULL == key) +      break; +    value = va_arg (args, char *); +    if (NULL == value) +      continue; +    GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); +    iparam++; +    GNUNET_buffer_write_str (&buf, key); +    GNUNET_buffer_write_str (&buf, "="); +    buffer_write_urlencode (&buf, value); +  } +  va_end (args2); + +  return GNUNET_buffer_reap_str (&buf); +} + + +/** + * Make an absolute URL for the given parameters. + * + * @param proto protocol for the URL (typically https) + * @param host hostname for the URL + * @param prefix prefix for the URL + * @param path path for the URL + * @param ... NULL-terminated key-value pairs (char *) for query parameters, + *        the value will be url-encoded + * @returns the URL, must be freed with #GNUNET_free + */ +char * +TALER_url_absolute_raw (const char *proto, +                        const char *host, +                        const char *prefix, +                        const char *path, +                        ...) +{ +  char *result; +  va_list args; + +  va_start (args, path); +  result = TALER_url_absolute_raw_va (proto, host, prefix, path, args); +  va_end (args); +  return result; +} + + +/** + * Find out if an MHD connection is using HTTPS (either + * directly or via proxy). + * + * @param connection MHD connection + * @returns GNUNET_YES if the MHD connection is using https, + *          GNUNET_NO if the MHD connection is using http, + *          GNUNET_SYSERR if the connection type couldn't be determined + */ +int +TALER_mhd_is_https (struct MHD_Connection *connection) +{ +  const union MHD_ConnectionInfo *ci; +  const union MHD_DaemonInfo *di; +  const char *forwarded_proto = MHD_lookup_connection_value (connection, +                                                             MHD_HEADER_KIND, +                                                             "X-Forwarded-Proto"); + +  if (NULL != forwarded_proto) +  { +    if (0 == strcmp (forwarded_proto, "https")) +      return GNUNET_YES; +    if (0 == strcmp (forwarded_proto, "http")) +      return GNUNET_NO; +    GNUNET_break (0); +    return GNUNET_SYSERR; +  } +  /* likely not reverse proxy, figure out if we are +     http by asking MHD */ +  ci = MHD_get_connection_info (connection, +                                MHD_CONNECTION_INFO_DAEMON); +  if (NULL == ci) +  { +    GNUNET_break (0); +    return GNUNET_SYSERR; +  } +  di = MHD_get_daemon_info (ci->daemon, +                            MHD_DAEMON_INFO_FLAGS); +  if (NULL == di) +  { +    GNUNET_break (0); +    return GNUNET_SYSERR; +  } +  if (0 != (di->flags & MHD_USE_TLS)) +    return GNUNET_YES; +  return GNUNET_NO; +} + + +/** + * Make an absolute URL for a given MHD connection. + * + * @param connection the connection to get the URL for + * @param path path of the url + * @param ... NULL-terminated key-value pairs (char *) for query parameters, + *        the value will be url-encoded + * @returns the URL, must be freed with #GNUNET_free + */ +char * +TALER_url_absolute_mhd (struct MHD_Connection *connection, +                        const char *path, +                        ...) +{ +  /* By default we assume we're running under HTTPS */ +  const char *proto; +  const char *host; +  const char *forwarded_host; +  const char *prefix; +  va_list args; +  char *result; + +  if (GNUNET_YES == TALER_mhd_is_https (connection)) +    proto = "https"; +  else +    proto = "http"; + +  host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Host"); +  forwarded_host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, +                                                "X-Forwarded-Host"); + +  prefix = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, +                                        "X-Forwarded-Prefix"); +  if (NULL == prefix) +    prefix = ""; + +  if (NULL != forwarded_host) +    host = forwarded_host; + +  if (NULL == host) +  { +    /* Should never happen, at last the host header should be defined */ +    GNUNET_break (0); +    return NULL; +  } + +  va_start (args, path); +  result = TALER_url_absolute_raw_va (proto, host, prefix, path, args); +  va_end (args); +  return result; +} + + +/* end of url.c */ diff --git a/src/util/util.c b/src/util/util.c index c9fd5a81..f49bc7c2 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -15,16 +15,13 @@  */  /**   * @file util.c - * @brief Common utility functions; we might choose to move those to GNUnet at some point + * @brief Common utility functions   * @author Sree Harsha Totakura <sreeharsha@totakura.in>   * @author Florian Dold   * @author Benedikt Mueller   */ -  #include "platform.h" -#include "gnunet/gnunet_buffer_lib.h"  #include "taler_util.h" -#include <gcrypt.h>  /** @@ -59,547 +56,4 @@ TALER_b2s (const void *buf,  } -/** - * Obtain denomination amount from configuration file. - * - * @param cfg configuration to use - * @param section section of the configuration to access - * @param option option of the configuration to access - * @param[out] denom set to the amount found in configuration - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_config_get_denom (const struct GNUNET_CONFIGURATION_Handle *cfg, -                        const char *section, -                        const char *option, -                        struct TALER_Amount *denom) -{ -  char *str; - -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_get_value_string (cfg, -                                             section, -                                             option, -                                             &str)) -    return GNUNET_NO; -  if (GNUNET_OK != TALER_string_to_amount (str, -                                           denom)) -  { -    GNUNET_free (str); -    return GNUNET_SYSERR; -  } -  GNUNET_free (str); -  return GNUNET_OK; -} - - -/** - * Set an option with an amount from the command line.  A pointer to - * this function should be passed as part of the 'struct - * GNUNET_GETOPT_CommandLineOption' array to initialize options of - * this type. - * - * @param ctx command line processing context - * @param scls additional closure (will point to the `struct TALER_Amount`) - * @param option name of the option - * @param value actual value of the option as a string. - * @return #GNUNET_OK if parsing the value worked - */ -static int -set_amount (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, -            void *scls, -            const char *option, -            const char *value) -{ -  struct TALER_Amount *amount = scls; - -  (void) ctx; -  if (GNUNET_OK != -      TALER_string_to_amount (value, -                              amount)) -  { -    fprintf (stderr, -             _ ("Failed to parse amount in option `%s'\n"), -             option); -    return GNUNET_SYSERR; -  } - -  return GNUNET_OK; -} - - -/** - * Allow user to specify an amount on the command line. - * - * @param shortName short name of the option - * @param name long name of the option - * @param argumentHelp help text for the option argument - * @param description long help text for the option - * @param[out] amount set to the amount specified at the command line - */ -struct GNUNET_GETOPT_CommandLineOption -TALER_getopt_get_amount (char shortName, -                         const char *name, -                         const char *argumentHelp, -                         const char *description, -                         struct TALER_Amount *amount) -{ -  struct GNUNET_GETOPT_CommandLineOption clo = { -    .shortName =  shortName, -    .name = name, -    .argumentHelp = argumentHelp, -    .description = description, -    .require_argument = 1, -    .processor = &set_amount, -    .scls = (void *) amount -  }; - -  return clo; -} - - -/** - * Check if a character is reserved and should - * be urlencoded. - * - * @param c character to look at - * @return #GNUNET_YES if @a c needs to be urlencoded, - *         #GNUNET_NO otherwise - */ -static bool -is_reserved (char c) -{ -  switch (c) -  { -  case '0': case '1': case '2': case '3': case '4': -  case '5': case '6': case '7': case '8': case '9': -  case 'a': case 'b': case 'c': case 'd': case 'e': -  case 'f': case 'g': case 'h': case 'i': case 'j': -  case 'k': case 'l': case 'm': case 'n': case 'o': -  case 'p': case 'q': case 'r': case 's': case 't': -  case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': -  case 'A': case 'B': case 'C': case 'D': case 'E': -  case 'F': case 'G': case 'H': case 'I': case 'J': -  case 'K': case 'L': case 'M': case 'N': case 'O': -  case 'P': case 'Q': case 'R': case 'S': case 'T': -  case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': -  case '-': case '.': case '_': case '~': -    return GNUNET_NO; -  default: -    break; -  } -  return GNUNET_YES; -} - - -/** - * Get the length of a string after it has been - * urlencoded. - * - * @param s the string - * @returns the size of the urlencoded @a s - */ -static size_t -urlencode_len (const char *s) -{ -  size_t len = 0; -  for (; *s != '\0'; len++, s++) -    if (GNUNET_YES == is_reserved (*s)) -      len += 2; -  return len; -} - - -/** - * URL-encode a string according to rfc3986. - * - * @param buf buffer to write the result to - * @param s string to encode - */ -static void -buffer_write_urlencode (struct GNUNET_Buffer *buf, const char *s) -{ -  GNUNET_buffer_ensure_remaining (buf, urlencode_len (s) + 1); - -  for (size_t i = 0; i < strlen (s); i++) -  { -    if (GNUNET_YES == is_reserved (s[i])) -      GNUNET_buffer_write_fstr (buf, "%%%02X", s[i]); -    else -      buf->mem[buf->position++] = s[i]; -  } -} - - -/** - * URL-encode a string according to rfc3986. - * - * @param s string to encode - * @returns the urlencoded string, the caller must free it with GNUNET_free - */ -char * -TALER_urlencode (const char *s) -{ -  struct GNUNET_Buffer buf = { 0 }; - -  buffer_write_urlencode (&buf, s); -  return GNUNET_buffer_reap_str (&buf); -} - - -/** - * Make an absolute URL with query parameters. - * - * @param base_url absolute base URL to use - * @param path path of the url - * @param ... NULL-terminated key-value pairs (char *) for query parameters, - *        the value will be url-encoded - * @returns the URL (must be freed with #GNUNET_free) or - *          NULL if an error occured. - */ -char * -TALER_url_join (const char *base_url, -                const char *path, -                ...) -{ -  unsigned int iparam = 0; -  va_list args; -  struct GNUNET_Buffer buf = { 0 }; -  size_t len; - -  GNUNET_assert (NULL != base_url); -  GNUNET_assert (NULL != path); -  if (0 == strlen (base_url)) -  { -    /* base URL can't be empty */ -    GNUNET_break (0); -    return NULL; -  } -  if ('/' != base_url[strlen (base_url) - 1]) -  { -    /* Must be an actual base URL! */ -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Base URL `%s' does not end with '/'\n", -                base_url); -    return NULL; -  } -  if ('/' == path[0]) -  { -    /* The path must be relative. */ -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Path `%s' is not relative\n", -                path); -    return NULL; -  } - -  /* 1st pass: compute length */ -  len = strlen (base_url) + strlen (path) + 1; - -  va_start (args, path); -  while (1) -  { -    char *key; -    char *value; -    key = va_arg (args, char *); -    if (NULL == key) -      break; -    value = va_arg (args, char *); -    if (NULL == value) -      continue; -    len += urlencode_len (value) + strlen (key) + 2; -  } -  va_end (args); - -  GNUNET_buffer_prealloc (&buf, len); -  GNUNET_buffer_write_str (&buf, base_url); -  GNUNET_buffer_write_str (&buf, path); - -  va_start (args, path); -  while (1) -  { -    char *key; -    char *value; - -    key = va_arg (args, char *); -    if (NULL == key) -      break; -    value = va_arg (args, char *); -    if (NULL == value) -      continue; -    GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); -    iparam++; -    GNUNET_buffer_write_str (&buf, key); -    GNUNET_buffer_write_str (&buf, "="); -    buffer_write_urlencode (&buf, value); -  } -  va_end (args); - -  return GNUNET_buffer_reap_str (&buf); -} - - -/** - * Make an absolute URL for the given parameters. - * - * @param proto protocol for the URL (typically https) - * @param host hostname for the URL - * @param prefix prefix for the URL - * @param path path for the URL - * @param args NULL-terminated key-value pairs (char *) for query parameters, - *        the value will be url-encoded - * @returns the URL, must be freed with #GNUNET_free - */ -char * -TALER_url_absolute_raw_va (const char *proto, -                           const char *host, -                           const char *prefix, -                           const char *path, -                           va_list args) -{ -  struct GNUNET_Buffer buf = { 0 }; -  unsigned int iparam = 0; -  size_t len = 0; -  va_list args2; - -  len += strlen (proto) + strlen ("://") + strlen (host); -  len += strlen (prefix) + strlen (path); - -  va_copy (args2, args); -  while (1) -  { -    char *key; -    char *value; -    key = va_arg (args2, char *); -    if (NULL == key) -      break; -    value = va_arg (args2, char *); -    if (NULL == value) -      continue; -    len += urlencode_len (value) + strlen (key) + 2; -  } -  va_end (args2); - -  GNUNET_buffer_prealloc (&buf, len); - -  GNUNET_buffer_write_str (&buf, proto); -  GNUNET_buffer_write_str (&buf, "://"); -  GNUNET_buffer_write_str (&buf, host); - -  GNUNET_buffer_write_path (&buf, prefix); -  GNUNET_buffer_write_path (&buf, path); - -  va_copy (args2, args); -  while (1) -  { -    char *key; -    char *value; -    key = va_arg (args, char *); -    if (NULL == key) -      break; -    value = va_arg (args, char *); -    if (NULL == value) -      continue; -    GNUNET_buffer_write_str (&buf, (0 == iparam) ? "?" : "&"); -    iparam++; -    GNUNET_buffer_write_str (&buf, key); -    GNUNET_buffer_write_str (&buf, "="); -    buffer_write_urlencode (&buf, value); -  } -  va_end (args2); - -  return GNUNET_buffer_reap_str (&buf); -} - - -/** - * Make an absolute URL for the given parameters. - * - * @param proto protocol for the URL (typically https) - * @param host hostname for the URL - * @param prefix prefix for the URL - * @param path path for the URL - * @param ... NULL-terminated key-value pairs (char *) for query parameters, - *        the value will be url-encoded - * @returns the URL, must be freed with #GNUNET_free - */ -char * -TALER_url_absolute_raw (const char *proto, -                        const char *host, -                        const char *prefix, -                        const char *path, -                        ...) -{ -  char *result; -  va_list args; - -  va_start (args, path); -  result = TALER_url_absolute_raw_va (proto, host, prefix, path, args); -  va_end (args); -  return result; -} - - -/** - * Find out if an MHD connection is using HTTPS (either - * directly or via proxy). - * - * @param connection MHD connection - * @returns GNUNET_YES if the MHD connection is using https, - *          GNUNET_NO if the MHD connection is using http, - *          GNUNET_SYSERR if the connection type couldn't be determined - */ -int -TALER_mhd_is_https (struct MHD_Connection *connection) -{ -  const union MHD_ConnectionInfo *ci; -  const union MHD_DaemonInfo *di; -  const char *forwarded_proto = MHD_lookup_connection_value (connection, -                                                             MHD_HEADER_KIND, -                                                             "X-Forwarded-Proto"); - -  if (NULL != forwarded_proto) -  { -    if (0 == strcmp (forwarded_proto, "https")) -      return GNUNET_YES; -    if (0 == strcmp (forwarded_proto, "http")) -      return GNUNET_NO; -    GNUNET_break (0); -    return GNUNET_SYSERR; -  } -  /* likely not reverse proxy, figure out if we are -     http by asking MHD */ -  ci = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_DAEMON); -  if (NULL == ci) -  { -    GNUNET_break (0); -    return GNUNET_SYSERR; -  } -  di = MHD_get_daemon_info (ci->daemon, MHD_DAEMON_INFO_FLAGS); -  if (NULL == di) -  { -    GNUNET_break (0); -    return GNUNET_SYSERR; -  } -  if (0 != (di->flags & MHD_USE_TLS)) -    return GNUNET_YES; -  return GNUNET_NO; -} - - -/** - * Make an absolute URL for a given MHD connection. - * - * @param connection the connection to get the URL for - * @param path path of the url - * @param ... NULL-terminated key-value pairs (char *) for query parameters, - *        the value will be url-encoded - * @returns the URL, must be freed with #GNUNET_free - */ -char * -TALER_url_absolute_mhd (struct MHD_Connection *connection, -                        const char *path, -                        ...) -{ -  /* By default we assume we're running under HTTPS */ -  const char *proto; -  const char *host; -  const char *forwarded_host; -  const char *prefix; -  va_list args; -  char *result; - -  if (GNUNET_YES == TALER_mhd_is_https (connection)) -    proto = "https"; -  else -    proto = "http"; - -  host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Host"); -  forwarded_host = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, -                                                "X-Forwarded-Host"); - -  prefix = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, -                                        "X-Forwarded-Prefix"); -  if (NULL == prefix) -    prefix = ""; - -  if (NULL != forwarded_host) -    host = forwarded_host; - -  if (NULL == host) -  { -    /* Should never happen, at last the host header should be defined */ -    GNUNET_break (0); -    return NULL; -  } - -  va_start (args, path); -  result = TALER_url_absolute_raw_va (proto, host, prefix, path, args); -  va_end (args); -  return result; -} - - -/** - * Prefix of PAYTO URLs. - */ -#define PAYTO "payto://" - - -/** - * Obtain the payment method from a @a payto_uri - * - * @param payto_uri the URL to parse - * @return NULL on error (malformed @a payto_uri) - */ -char * -TALER_payto_get_method (const char *payto_uri) -{ -  const char *start; -  const char *end; - -  if (0 != strncmp (payto_uri, -                    PAYTO, -                    strlen (PAYTO))) -    return NULL; -  start = &payto_uri[strlen (PAYTO)]; -  end = strchr (start, -                (unsigned char) '/'); -  if (NULL == end) -    return NULL; -  return GNUNET_strndup (start, -                         end - start); -} - - -/** - * Obtain the account name from a payto URL. - * - * @param payto an x-taler-bank payto URL - * @return only the account name from the @a payto URL, NULL if not an x-taler-bank - *   payto URL - */ -char * -TALER_xtalerbank_account_from_payto (const char *payto) -{ -  const char *beg; -  const char *end; - -  if (0 != strncasecmp (payto, -                        "payto://x-taler-bank/", -                        strlen ("payto://x-taler-bank/"))) -    return NULL; -  beg = strchr (&payto[strlen ("payto://x-taler-bank/")], -                '/'); -  if (NULL == beg) -    return NULL; -  beg++; -  end = strchr (beg, -                '?'); -  if (NULL == end) -    return GNUNET_strdup (beg); -  return GNUNET_strndup (beg, -                         end - beg); -} - -  /* end of util.c */ | 
