diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-04-16 08:42:36 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-04-16 08:42:36 +0200 |
commit | e9e57dcf55cf931020ddefe5e08995fe68f660b5 (patch) | |
tree | b3b5443553427d81329e4d43ff2f6988d37567a4 /src/util | |
parent | 09e315eedb73adc9fa7d11061728cd433bee9f31 (diff) |
allow x-taler-bank with paht (fixes #8739)
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.am | 2 | ||||
-rw-r--r-- | src/util/payto.c | 72 | ||||
-rw-r--r-- | src/util/test_payto.c | 39 |
3 files changed, 84 insertions, 29 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index ed3f382d3..d2504588b 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -120,7 +120,7 @@ libtalerutil_la_LIBADD = \ -lm libtalerutil_la_LDFLAGS = \ - -version-info 3:2:2 \ + -version-info 3:3:2 \ -no-undefined diff --git a/src/util/payto.c b/src/util/payto.c index 5e0391883..6092b73fd 100644 --- a/src/util/payto.c +++ b/src/util/payto.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2019-2022 Taler Systems SA + Copyright (C) 2019-2024 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 @@ -101,7 +101,9 @@ TALER_payto_get_method (const char *payto_uri) char * TALER_xtalerbank_account_from_payto (const char *payto) { + const char *host; const char *beg; + const char *nxt; const char *end; if (0 != strncasecmp (payto, @@ -111,23 +113,27 @@ TALER_xtalerbank_account_from_payto (const char *payto) GNUNET_break_op (0); return NULL; } - beg = strchr (&payto[strlen (PAYTO "x-taler-bank/")], + host = &payto[strlen (PAYTO "x-taler-bank/")]; + beg = strchr (host, '/'); if (NULL == beg) { GNUNET_break_op (0); return NULL; } - beg++; /* now points to $ACCOUNT */ + beg++; /* now points to $ACCOUNT or $PATH */ + nxt = strchr (beg, + '/'); end = strchr (beg, '?'); if (NULL == end) + end = &beg[strlen (beg)]; + while ( (NULL != nxt) && + (end - nxt > 0) ) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid payto URI `%s'\n", - payto); - GNUNET_break_op (0); - return GNUNET_strdup (beg); /* optional part is missing */ + beg = nxt + 1; + nxt = strchr (beg, + '/'); } return GNUNET_strndup (beg, end - beg); @@ -200,36 +206,63 @@ static char * validate_payto_xtalerbank (const char *account_url) { const char *user; + const char *nxt; + const char *beg; + const char *end; const char *host; bool dot_ok; bool post_colon; + bool port_ok; -#define XTALERBANK_PREFIX "payto://x-taler-bank/" +#define XTALERBANK_PREFIX PAYTO "x-taler-bank/" if (0 != strncasecmp (account_url, XTALERBANK_PREFIX, strlen (XTALERBANK_PREFIX))) return NULL; /* not an IBAN */ host = &account_url[strlen (XTALERBANK_PREFIX)]; #undef XTALERBANK_PREFIX - user = strchr (host, '/'); - if (NULL == user) + beg = strchr (host, + '/'); + if (NULL == beg) { return GNUNET_strdup ("account name missing"); } - if (user == host) + beg++; /* now points to $ACCOUNT or $PATH */ + nxt = strchr (beg, + '/'); + end = strchr (beg, + '?'); + if (NULL == end) + { + return GNUNET_strdup ("'receiver-name' parameter missing"); + } + while ( (NULL != nxt) && + (end - nxt > 0) ) + { + beg = nxt + 1; + nxt = strchr (beg, + '/'); + } + user = beg; + if (user == host + 1) { return GNUNET_strdup ("domain name missing"); } if ('-' == host[0]) return GNUNET_strdup ("invalid character '-' at start of domain name"); - if (NULL != strchr (user + 1, '/')) - return GNUNET_strdup ("invalid character '/' after account name"); dot_ok = false; post_colon = false; + port_ok = false; while (host != user) { char c = host[0]; + if ('/' == c) + { + /* path started, do not care about characters + in the path */ + break; + } if (':' == c) { post_colon = true; @@ -247,6 +280,7 @@ validate_payto_xtalerbank (const char *account_url) c); return err; } + port_ok = true; } else { @@ -275,6 +309,10 @@ validate_payto_xtalerbank (const char *account_url) } host++; } + if (post_colon && (! port_ok) ) + { + return GNUNET_strdup ("port missing after ':'"); + } { char *target; @@ -304,7 +342,7 @@ TALER_payto_validate (const char *payto_uri) /* This is more strict than RFC 8905, alas we do not need to support messages/instructions/etc., and it is generally better to start with a narrow whitelist; we can be more permissive later ...*/ #define ALLOWED_CHARACTERS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/:&?-.,=+%" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/:&?-.,=+%~" if (NULL == strchr (ALLOWED_CHARACTERS, (int) payto_uri[i])) { @@ -358,10 +396,10 @@ TALER_payto_get_receiver_name (const char *payto) /** - * Normalize "payto://x-taler-bank/$HOSTNAME/$USERNAME" + * Normalize "payto://x-taler-bank/$HOSTNAME/[$PATH/]$USERNAME" * URI in @a input. * - * Converts to lower-case, except for $USERNAME which + * Converts to lower-case, except for [$PATH/]$USERNAME which * is case-sensitive. * * @param len number of bytes in @a input diff --git a/src/util/test_payto.c b/src/util/test_payto.c index b37a6f721..62ba7d28e 100644 --- a/src/util/test_payto.c +++ b/src/util/test_payto.c @@ -22,16 +22,16 @@ #include "taler_util.h" #define CHECK(a,b) do { \ - GNUNET_assert (a != NULL); \ - GNUNET_assert (b != NULL); \ - if (0 != strcmp (a,b)) { \ - GNUNET_break (0); \ - fprintf (stderr, "Got %s, wanted %s\n", b, a); \ - GNUNET_free (b); \ - return 1; \ - } else { \ - GNUNET_free (b); \ - } \ + GNUNET_assert (a != NULL); \ + GNUNET_assert (b != NULL); \ + if (0 != strcmp (a,b)) { \ + GNUNET_break (0); \ + fprintf (stderr, "Got %s, wanted %s\n", b, a); \ + GNUNET_free (b); \ + return 1; \ + } else { \ + GNUNET_free (b); \ + } \ } while (0) @@ -54,11 +54,20 @@ main (int argc, "payto://x-taler-bank/hostname/username?receiver-name=foo"); GNUNET_assert (NULL == r); r = TALER_payto_validate ( + "payto://x-taler-bank/hostname/~path/username?receiver-name=foo"); + GNUNET_assert (NULL == r); + r = TALER_payto_validate ( + "payto://x-taler-bank/hostname/~path/username?receiver-name=fo/o"); + GNUNET_assert (NULL == r); + r = TALER_payto_validate ( + "payto://x-taler-bank/hostname/path/username?receiver-name=foo"); + GNUNET_assert (NULL == r); + r = TALER_payto_validate ( "payto://x-taler-bank/https://hostname/username?receiver-name=foo"); GNUNET_assert (NULL != r); GNUNET_free (r); r = TALER_payto_validate ( - "payto://x-taler-bank/hostname/username/extra?receiver-name=foo"); + "payto://x-taler-bank/hostname:4a2/path/username?receiver-name=foo"); GNUNET_assert (NULL != r); GNUNET_free (r); r = TALER_payto_validate ( @@ -82,6 +91,14 @@ main (int argc, CHECK ("alice", r); r = TALER_xtalerbank_account_from_payto ( + "payto://x-taler-bank/localhost:1080/path/alice"); + CHECK ("alice", + r); + r = TALER_xtalerbank_account_from_payto ( + "payto://x-taler-bank/localhost:1080/path/alice?receiver-name=ali/cia"); + CHECK ("alice", + r); + r = TALER_xtalerbank_account_from_payto ( "payto://x-taler-bank/localhost:1080/alice?subject=hello&amount=EUR:1"); CHECK ("alice", r); |