taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

commit 60cc468cad2b18d8c7ec23ae648747b5dfc47e08
parent fb727bfcffe8f88140f17ba95b69a93527a1d7f9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 13 Oct 2026 23:31:35 +0200

manpages: document the three EEA SMS helpers for Challenger

adds challenger-send-sms-seven, -gatewayapi and -budgetsms

Diffstat:
Mconf.py | 21+++++++++++++++++++++
Mmanpages/challenger-send-sms-aspsms.1.rst | 4+++-
Amanpages/challenger-send-sms-budgetsms.1.rst | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmanpages/challenger-send-sms-clicksend.1.rst | 4+++-
Amanpages/challenger-send-sms-gatewayapi.1.rst | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanpages/challenger-send-sms-seven.1.rst | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmanpages/challenger-send-sms-telesign.1.rst | 4+++-
Mmanpages/challenger-send-sms.1.rst | 25+++++++++++++++++++++----
Mmanpages/challenger.conf.5.rst | 12++++++++----
Mtaler-challenger-manual.rst | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
10 files changed, 671 insertions(+), 15 deletions(-)

diff --git a/conf.py b/conf.py @@ -401,6 +401,13 @@ man_pages = [ 1, ), ( + "manpages/challenger-send-sms-budgetsms.1", + "challenger-send-sms-budgetsms", + "transmit a Challenger TAN by SMS via BudgetSMS", + "GNU Taler contributors", + 1, + ), + ( "manpages/challenger-send-sms-clicksend.1", "challenger-send-sms-clicksend", "transmit a Challenger TAN by SMS via ClickSend", @@ -408,6 +415,20 @@ man_pages = [ 1, ), ( + "manpages/challenger-send-sms-gatewayapi.1", + "challenger-send-sms-gatewayapi", + "transmit a Challenger TAN by SMS via GatewayAPI", + "GNU Taler contributors", + 1, + ), + ( + "manpages/challenger-send-sms-seven.1", + "challenger-send-sms-seven", + "transmit a Challenger TAN by SMS via seven.io", + "GNU Taler contributors", + 1, + ), + ( "manpages/challenger-send-sms-telesign.1", "challenger-send-sms-telesign", "transmit a Challenger TAN by SMS via Telesign", diff --git a/manpages/challenger-send-sms-aspsms.1.rst b/manpages/challenger-send-sms-aspsms.1.rst @@ -125,7 +125,9 @@ See Also ======== challenger-send-sms(1), challenger-send-sms-clicksend(1), -challenger-send-sms-telesign(1), challenger-httpd(1), challenger.conf(5). +challenger-send-sms-telesign(1), challenger-send-sms-seven(1), +challenger-send-sms-gatewayapi(1), challenger-send-sms-budgetsms(1), +challenger-httpd(1), challenger.conf(5). Bugs diff --git a/manpages/challenger-send-sms-budgetsms.1.rst b/manpages/challenger-send-sms-budgetsms.1.rst @@ -0,0 +1,170 @@ +challenger-send-sms-budgetsms(1) +################################ + +.. only:: html + + Name + ==== + + **challenger-send-sms-budgetsms** - transmit a Challenger TAN by SMS via BudgetSMS + + +Synopsis +======== + +**challenger-send-sms-budgetsms** *PHONE_NUMBER* + + +Description +=========== + +**challenger-send-sms-budgetsms** transmits a TAN to a mobile phone number +using the BudgetSMS HTTP API. + +It is normally invoked by challenger-send-sms(1) as one provider in a fallback +chain, and not directly. Its calling convention differs from that of the +dispatcher: *PHONE_NUMBER* is the **bare phone number**, already extracted from +the address object and already checked for general E.164 form. The message to +transmit, including the TAN, is read from **standard input**. + +Unlike the other provider helpers, this API returns no JSON. Every call answers +with a single line, either ``OK`` followed by a value or ``ERR`` followed by a +numeric error code, always with HTTP status 200. A successful submission +returns the identifier of the message and means only that BudgetSMS handed the +message to one of its uplinks; it already deducts credit, while a submission +reported as an error does not. Delivery is confirmed separately by polling the +delivery status for that identifier, for a bounded period. A message still in +flight when the polling window closes is reported as accepted, not as a +failure. + +The error codes returned at submission are the most detailed of any configured +provider for the shape of the number: a number that is too short, one that is +not numeric or formatted invalidly, and one that is simply invalid as a +destination are distinguished from each other. There is no code for a number +that is too long. + +**The delivery statuses carry no reason code.** The status for a failed +delivery says only that delivery failed, so it is reported as unclassified +rather than guessed at as a bad number, which also lets the dispatcher try the +next provider. The statuses that mean the outcome is unknown are only reachable +24 to 72 hours after sending and thus never within the polling window. + +This API requires a sender identity on every message, so unlike the other +helpers this one sends a default sender that can be overridden; see +**BUDGETSMS_SENDER** below. + + +Environment +=========== + +**BUDGETSMS_USERNAME** + BudgetSMS account username. Required. + +**BUDGETSMS_USERID** + Numeric BudgetSMS user id. Required. The helper fails with status 40 if the + value is not a sequence of digits, as it is used to build the request URL. + +**BUDGETSMS_HANDLE** + BudgetSMS API handle, the account's API credential. Required. + +**BUDGETSMS_SENDER** + Sender identity to show on the message, at most 11 alphanumeric or 16 + numeric characters. Optional, defaults to ``Challenger``. An alphanumeric + sender must be pre-registered with the operator in several countries; where + that applies, configure a sender the operator accepts, or a numeric one. + +The helper fails with status 40 if any of the three required variables is unset +or empty. Credentials are taken from the environment of the invoking daemon, +never from a configuration file. + + +Exit Status +=========== + +An exit status of 0, or in the 200 to 210 band, means the TAN was +transmitted, or will be. Any other status means it was not. The success +band starts at 200 rather than at 1 because GNUnet reports a helper it +could not execute as exit status 1, which must not be mistaken for a +delivery. The subset below is what this helper can actually +report; see challenger-send-sms(1) for the full table. + +**0** + Delivery to the handset was confirmed. + +**201** + BudgetSMS accepted the message but delivery was not confirmed within the + polling window, including the case of a message that has been sent but not + yet acknowledged by the handset. + +**10** + The destination is not numeric, is empty, or is formatted invalidly. + +**11** + The destination number is too short. + +**14** + The destination is invalid: either rejected as such at submission, or + reported as an invalid destination address in the delivery status. + +**15** + The message was not allowed to the destination. + +**21** + The message expired before it could be delivered. + +**22** + The service centre could not process the message, or the route reported a + wrong operator for the destination. + +**30** + BudgetSMS is unavailable or timed out, there is no route to the destination, + the gateway is unreachable, a system error occurred, or the message was + never sent. + +**31** + BudgetSMS rejected the request, for instance because the message identifier + used for the delivery query was invalid or a custom identifier had already + been used. + +**32** + BudgetSMS answered with a rate-limit HTTP status. + +**40** + **BUDGETSMS_USERNAME**, **BUDGETSMS_USERID** or **BUDGETSMS_HANDLE** is not + set or empty, **BUDGETSMS_USERID** is not numeric, the helper was invoked + with the wrong number of arguments, or BudgetSMS rejected a parameter of the + request such as an empty or over-long message, an unacceptable sender, a + character-set problem, or an account without a route set up. + +**41** + BudgetSMS refused the credentials, the account is not active, or the request + came from an IP address that is not registered for the account. + +**42** + The pre-paid BudgetSMS account has insufficient credits to send messages. + +**50** + Delivery failed with no reason given, or BudgetSMS reported an unknown error + or a code that could not be classified. + +BudgetSMS has no error code for a number that is too long, so status 12 is +never reported; none that means an identical message is already in flight, so +status 202 is never reported; and neither its error codes nor its delivery +statuses distinguish a non-mobile subscription from an unreachable handset, so +status 13 and 20 are never reported either. + + +See Also +======== + +challenger-send-sms(1), challenger-send-sms-seven(1), +challenger-send-sms-gatewayapi(1), challenger-send-sms-aspsms(1), +challenger-send-sms-clicksend(1), challenger-send-sms-telesign(1), +challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-send-sms-clicksend.1.rst b/manpages/challenger-send-sms-clicksend.1.rst @@ -134,7 +134,9 @@ See Also ======== challenger-send-sms(1), challenger-send-sms-aspsms(1), -challenger-send-sms-telesign(1), challenger-httpd(1), challenger.conf(5). +challenger-send-sms-telesign(1), challenger-send-sms-seven(1), +challenger-send-sms-gatewayapi(1), challenger-send-sms-budgetsms(1), +challenger-httpd(1), challenger.conf(5). Bugs diff --git a/manpages/challenger-send-sms-gatewayapi.1.rst b/manpages/challenger-send-sms-gatewayapi.1.rst @@ -0,0 +1,187 @@ +challenger-send-sms-gatewayapi(1) +################################# + +.. only:: html + + Name + ==== + + **challenger-send-sms-gatewayapi** - transmit a Challenger TAN by SMS via GatewayAPI + + +Synopsis +======== + +**challenger-send-sms-gatewayapi** *PHONE_NUMBER* + + +Description +=========== + +**challenger-send-sms-gatewayapi** transmits a TAN to a mobile phone number +using the GatewayAPI REST API. + +It is normally invoked by challenger-send-sms(1) as one provider in a fallback +chain, and not directly. Its calling convention differs from that of the +dispatcher: *PHONE_NUMBER* is the **bare phone number**, already extracted from +the address object and already checked for general E.164 form. The message to +transmit, including the TAN, is read from **standard input**. + +The provider runs two platforms: ``gatewayapi.eu``, on which hosting, +ownership and routing stay inside the European Union, and +``gatewayapi.com``. This helper uses the EU platform unless told +otherwise, and an API token is only valid on the platform it was +created for. + +A submission that is accepted returns a message id and means only that +GatewayAPI took the message. Delivery is confirmed separately by polling the +message by that id, for a bounded period. A message still in flight when the +polling window closes is reported as accepted, not as a failure. The polling +request answers with HTTP 404 until the message has been transferred to +long-term storage, which is not an error. + +GatewayAPI carries its diagnosis in the body of a failed request, as a 32-bit +error code written in hexadecimal whose first byte identifies the origin of the +error: the API itself, the subscriber database, the mobile switching centre, a +screening rule, the service centre, routing, the SMSC protocol, the service +provider, or GatewayAPI's own filters. Every code ending in ``00`` to ``0F`` is +a generic placeholder whose meaning depends on its context; such a code does not +override the classification implied by the delivery status itself. The same +codes accompany a delivery status notification, which is what lets this helper +distinguish an unknown subscriber from a barred one, a switched-off handset +from a congested network, and a message blocked by a content filter from one +the operator never accepted. + +A delivery status of ``UNDELIVERABLE`` without an accompanying code is reported +as a problem with the number, which is how GatewayAPI documents that status. A +status of ``REJECTED`` or ``SKIPPED`` without a code is reported as a carrier +failure rather than as a barred number: without a code naming a filter there is +no evidence that the number itself is at fault, and the next provider takes a +different route. A status of ``ACCEPTED`` is final, but it means the operator +accepted the message on the subscriber's behalf rather than the handset +confirming receipt, so it is reported as accepted rather than as delivered. + +Environment +=========== + +**GATEWAYAPI_TOKEN** + API token for the GatewayAPI REST API, as created in the GatewayAPI + dashboard of the platform in use. Required. The helper fails with status 40 + if it is unset or empty, or if it contains a line break, as the token is + sent in an HTTP header. + +**GATEWAYAPI_BASE_URL** + Base URL of the GatewayAPI platform to use. Optional, defaults to + ``https://gatewayapi.eu``, the platform that keeps hosting and routing + inside the European Union. Set it to ``https://gatewayapi.com`` for an + account on the global platform. A token is only valid on the platform it was + created for, so a mismatch is reported as a refused credential. + +Credentials are taken from the environment of the invoking daemon, never from a +configuration file. + +No sender identity is configured by this helper: the account default applies. +An alphanumeric sender must be pre-registered with the operator in several +countries, and a sender the operator does not accept fails every message. + + +Exit Status +=========== + +An exit status of 0, or in the 200 to 210 band, means the TAN was +transmitted, or will be. Any other status means it was not. The success +band starts at 200 rather than at 1 because GNUnet reports a helper it +could not execute as exit status 1, which must not be mistaken for a +delivery. The subset below is what this helper can actually +report; see challenger-send-sms(1) for the full table. + +**0** + Delivery to the handset was confirmed. + +**201** + GatewayAPI accepted the message but delivery was not confirmed within the + polling window, including the case of a message still en route or buffered, + and the case of the operator accepting the message on the subscriber's + behalf. + +**13** + The subscription cannot receive SMS: the teleservice is not provisioned, the + facility is not supported, or the equipment is not short-message equipped. + +**14** + The subscriber is unknown or unidentified, the destination address is + invalid, its number plan or network type is not supported, or the number + matches a pattern known to be unreachable. + +**15** + Delivery is barred or screened: the subscriber is barred or illegal, a + screening rule applies, or a GatewayAPI content or destination filter + stopped the message. + +**20** + The subscriber is absent, detached, busy for mobile-terminated SMS, out of + handset memory, or out of pre-paid credit. + +**21** + The message was not delivered before its validity period expired. + +**22** + A mobile network component failed, a service centre was congested, routing + failed, the operator timed out, or the network declined to carry the message + without naming a filter. + +**30** + GatewayAPI is unavailable, timed out, reported an internal error, or its + outbound queue is full. + +**31** + GatewayAPI rejected the request, or the protocol exchange between the + gateway and the service centre failed. + +**32** + A rate limit was exceeded, or a quota for the destination was exhausted. + +**33** + The submission was answered with a success status but without a message id, + so whether the message was accepted could not be determined. + +**40** + **GATEWAYAPI_TOKEN** is not set, is empty, or contains a line break; the + helper was invoked with the wrong number of arguments; or the account is not + authorized for the destination country or operator, the message class is not + configured, a parameter was missing or unsupported, or the submitted message + or sender was unacceptable. + +**41** + GatewayAPI refused the token or the account: invalid credentials, an + unauthorized or unknown IP address, a frozen account, or an account for + which SMS is not enabled. A token created for the other platform is also + reported here. + +**42** + The GatewayAPI account has insufficient credit to send the message. + +**50** + The delivery failed with a code that names no cause, such as the unspecified + delivery error, or with a code that could not be classified. + +GatewayAPI has no submission-time check that distinguishes a number that is +merely too short or too long, so status 11 and 12 are never reported, and +nothing in its error table means that an identical message is already in +flight, so status 202 is never reported either. + + +See Also +======== + +challenger-send-sms(1), challenger-send-sms-seven(1), +challenger-send-sms-budgetsms(1), challenger-send-sms-aspsms(1), +challenger-send-sms-clicksend(1), challenger-send-sms-telesign(1), +challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-send-sms-seven.1.rst b/manpages/challenger-send-sms-seven.1.rst @@ -0,0 +1,156 @@ +challenger-send-sms-seven(1) +############################ + +.. only:: html + + Name + ==== + + **challenger-send-sms-seven** - transmit a Challenger TAN by SMS via seven.io + + +Synopsis +======== + +**challenger-send-sms-seven** *PHONE_NUMBER* + + +Description +=========== + +**challenger-send-sms-seven** transmits a TAN to a mobile phone number using +the seven.io REST/HTTP API. + +It is normally invoked by challenger-send-sms(1) as one provider in a fallback +chain, and not directly. Its calling convention differs from that of the +dispatcher: *PHONE_NUMBER* is the **bare phone number**, already extracted from +the address object and already checked for general E.164 form. The message to +transmit, including the TAN, is read from **standard input**. + +seven.io answers with HTTP 200 even for an authentication failure and reports +the outcome in the ``success`` field of the response body, which carries a +numeric return code. A submission that is accepted only means the gateway took +the message; delivery is confirmed separately by polling the outbound logbook +for the returned message id, for a bounded period. A message still in flight +when the polling window closes is reported as accepted, not as a failure. + +A single bad-number code covers every unusable recipient, so a number that is +malformed, too short, too long or unallocated cannot be distinguished at +submission time. + +seven.io blocks a message whose text and recipient are identical to one +accepted within the previous three minutes. Because the suppressed message is by +definition identical to one already accepted, the TAN will still reach the user, +and this is reported as a success. Note that a deployment may switch this block +off in its seven.io account settings, in which case duplicates are charged for +and this helper never reports that status. The provider also enforces a daily +cap per recipient number; since another provider keeps its own counter, that is +reported as a rate limit rather than as a problem with the number. + +**The delivery report carries no reason code**, only a status word. A confirmed +non-delivery for which the status word itself names no cause is therefore +reported as unclassified rather than guessed at as a bad number, which also +lets the dispatcher try the next provider. + +The logbook entry returned while polling echoes the message text, and hence the +TAN, back to the helper. Like every Challenger helper, this one writes status +diagnostics rather than provider responses to standard error, so the TAN does +not reach the log of the invoking daemon. + + +Environment +=========== + +**SEVEN_API_KEY** + API key for the seven.io REST/HTTP API, as created in the developer area of + the seven.io dashboard. Required. The helper fails with status 40 if it is + unset or empty, or if it contains a line break, as the key is sent in an + HTTP header. + +Credentials are taken from the environment of the invoking daemon, never from a +configuration file. + +No sender identity is configured by this helper: the account default applies. +An alphanumeric sender must be pre-registered with the operator in several +countries, and a sender the operator does not accept fails every message. + + +Exit Status +=========== + +An exit status of 0, or in the 200 to 210 band, means the TAN was +transmitted, or will be. Any other status means it was not. The success +band starts at 200 rather than at 1 because GNUnet reports a helper it +could not execute as exit status 1, which must not be mistaken for a +delivery. The subset below is what this helper can actually +report; see challenger-send-sms(1) for the full table. + +**0** + Delivery to the handset was confirmed. + +**201** + seven.io accepted the message but delivery was not confirmed within the + polling window, including the case of a message buffered for a handset that + is switched off. + +**202** + The message was suppressed as a duplicate of one accepted for the same + recipient within the previous three minutes. The earlier copy carries the + same TAN and is in flight. + +**14** + The recipient number was rejected by the gateway. This one code covers a + malformed, too short, too long or unallocated number alike. + +**21** + The message was not delivered before its validity period expired. + +**22** + The network operator rejected the message. + +**30** + seven.io is unavailable, timed out, or reported an error while sending. + +**31** + seven.io answered with something other than one of its documented return + codes, together with a client-error HTTP status. + +**32** + The daily limit for this recipient number has been reached. + +**40** + **SEVEN_API_KEY** is not set, is empty, or contains a line break; the helper + was invoked with the wrong number of arguments; or the gateway rejected a + parameter of the request, such as the configured sender, a message that is + too long, or a parameter it does not support. + +**41** + seven.io refused the API key, the key has no access to the endpoint, or the + request came from an IP address that is not on the account's permitted list. + +**42** + The pre-paid seven.io account has insufficient credit to send the message. + +**50** + The message was reported as not delivered, with no reason given, or the + gateway reported a return code that could not be classified. + +Because the delivery report has no reason code, this helper never reports +status 13, 15 or 20, and the single bad-number code means it never reports +status 11 or 12. + + +See Also +======== + +challenger-send-sms(1), challenger-send-sms-gatewayapi(1), +challenger-send-sms-budgetsms(1), challenger-send-sms-aspsms(1), +challenger-send-sms-clicksend(1), challenger-send-sms-telesign(1), +challenger-httpd(1), challenger.conf(5). + + +Bugs +==== + +Report bugs by using https://bugs.taler.net or by sending electronic +mail to <taler@gnu.org>. diff --git a/manpages/challenger-send-sms-telesign.1.rst b/manpages/challenger-send-sms-telesign.1.rst @@ -120,7 +120,9 @@ See Also ======== challenger-send-sms(1), challenger-send-sms-aspsms(1), -challenger-send-sms-clicksend(1), challenger-httpd(1), challenger.conf(5). +challenger-send-sms-clicksend(1), challenger-send-sms-seven(1), +challenger-send-sms-gatewayapi(1), challenger-send-sms-budgetsms(1), +challenger-httpd(1), challenger.conf(5). Bugs diff --git a/manpages/challenger-send-sms.1.rst b/manpages/challenger-send-sms.1.rst @@ -54,6 +54,19 @@ Providers are resolved by name from the directory holding tried in the order ``telesign``, ``clicksend``, ``aspsms``. A provider whose helper is absent or not executable is skipped silently. +Three further provider helpers are installed but not in that list: +``seven`` (challenger-send-sms-seven(1)), ``gatewayapi`` +(challenger-send-sms-gatewayapi(1)) and ``budgetsms`` +(challenger-send-sms-budgetsms(1)). All three are operated inside the European +Economic Area, which avoids the transfer of a phone number and a TAN to a third +country that the other three providers involve. They have been written against +the published specifications of their APIs and are covered by the offline test +suite, but have not been exercised against a live account, which is why they +are not enabled by default. To use one, add its name to the ``PROVIDERS`` +variable near the top of the **challenger-send-sms** script, in the order in +which it should be tried; the credentials listed in each helper's manual page +must be present in the environment of the invoking daemon. + Whether a failing provider causes the next one to be tried depends on the class of the failure. An address that one provider rejects will be rejected by all of them, so such a failure is reported immediately; a provider that is @@ -71,7 +84,9 @@ Environment **challenger-send-sms** itself reads no environment variables, but the provider helpers it invokes require credentials to be present in the environment of the invoking daemon. See challenger-send-sms-telesign(1), -challenger-send-sms-clicksend(1) and challenger-send-sms-aspsms(1). +challenger-send-sms-clicksend(1), challenger-send-sms-aspsms(1), +challenger-send-sms-seven(1), challenger-send-sms-gatewayapi(1) and +challenger-send-sms-budgetsms(1). Exit Status @@ -156,9 +171,11 @@ delivery. See Also ======== -challenger-send-sms-aspsms(1), challenger-send-sms-clicksend(1), -challenger-send-sms-telesign(1), challenger-send-email(1), -challenger-send-post(1), challenger-httpd(1), challenger.conf(5). +challenger-send-sms-aspsms(1), challenger-send-sms-budgetsms(1), +challenger-send-sms-clicksend(1), challenger-send-sms-gatewayapi(1), +challenger-send-sms-seven(1), challenger-send-sms-telesign(1), +challenger-send-email(1), challenger-send-post(1), challenger-httpd(1), +challenger.conf(5). Bugs diff --git a/manpages/challenger.conf.5.rst b/manpages/challenger.conf.5.rst @@ -81,10 +81,14 @@ AUTH_COMMAND Command to execute to transmit the challenge code to the address. The value may include arguments separated by spaces. Quoting and escaping are not supported. The address is appended as the final argument, while the message - to send is provided on standard input. Templates (possibly without the - necessary credentials) for such commands are provided as - challenger-send-email.sh, challenger-send-post.sh and - challenger-send-sms.sh. + to send is provided on standard input. Commands for the three address types + in common use are provided by the ``taler-challenger-helpers`` package as + challenger-send-email(1), challenger-send-post(1) and + challenger-send-sms(1), the last of which dispatches to one of several SMS + provider helpers. They should be seen as examples as much as as finished + tools. The credentials these commands need are **not** configured here: they + are read from the environment of the invoking daemon, as documented in each + command's manual page. ADDRESS_TYPE Type of the address that is being collected, returned as part of the ``address_type`` in the ``/info`` endpoint. Examples include ``email`` or ``phone``. diff --git a/taler-challenger-manual.rst b/taler-challenger-manual.rst @@ -255,10 +255,12 @@ Challenger comes with ``AUTH_COMMAND`` shell scripts for sending e-mail, SMS and postal mail. Note that for SMS and postal mail the Challenger scripts use third party services to actually send the SMS or print and mail the postal mail. These third parties naturally charge money for their services, and thus -the Challenger administrator will need to add the respective credentials to -the SMS and postal mail scripts before they can function. In any case, these -scripts should be primarily seen as *examples* on how to write authentication -commands. +the Challenger administrator will need to obtain an account with one of them. +The scripts read the credentials from their **environment** rather than from a +configuration file, so they are configured by setting those variables for the +``challenger-httpd`` service and not by editing the scripts; see +*SMS transmission providers* below. In any case, these scripts should be +primarily seen as *examples* on how to write authentication commands. .. note:: @@ -266,6 +268,99 @@ commands. providers or for new types of addresses. +SMS transmission providers +-------------------------- + +The ``AUTH_COMMAND`` for phone numbers is ``challenger-send-sms``, which is not +itself an SMS sender: it checks the number, then runs each provider helper in +turn until one of them accepts the message. The helpers live next to it and are +named ``challenger-send-sms-``\ *PROVIDER*; which of them are tried, and in +which order, is the ``PROVIDERS`` variable near the top of the dispatcher +script. A helper that is not installed or not executable is skipped. + +Credentials are **not** configuration options in ``challenger.conf``. They are +read from the environment of the invoking daemon, so that they do not end up in +a world-readable configuration file nor in the process table. With systemd they +belong in a drop-in for the service, ideally through +``EnvironmentFile=`` pointing at a file readable only by the service user: + +.. code-block:: ini + :caption: /etc/systemd/system/challenger-httpd.service.d/sms.conf + + [Service] + EnvironmentFile=/etc/challenger/sms-credentials.env + +A helper whose credentials are missing or empty exits with status 40, which the +dispatcher treats as a configuration failure and falls through to the next +provider. + +.. list-table:: + :header-rows: 1 + :widths: 22 18 60 + + * - Helper + - Operated from + - Environment + * - ``challenger-send-sms-telesign`` + - United States + - ``TELESIGN_AUTH_TOKEN`` + * - ``challenger-send-sms-clicksend`` + - Australia + - ``CLICKSEND_USERNAME``, ``CLICKSEND_API_KEY`` + * - ``challenger-send-sms-aspsms`` + - Switzerland + - ``ASPSMS_USERKEY``, ``ASPSMS_PASSWORD`` + * - ``challenger-send-sms-seven`` + - Germany + - ``SEVEN_API_KEY`` + * - ``challenger-send-sms-gatewayapi`` + - Denmark + - ``GATEWAYAPI_TOKEN``, optionally ``GATEWAYAPI_BASE_URL`` + * - ``challenger-send-sms-budgetsms`` + - Netherlands + - ``BUDGETSMS_USERNAME``, ``BUDGETSMS_USERID``, ``BUDGETSMS_HANDLE``, + optionally ``BUDGETSMS_SENDER`` + +Two of the variables above are not credentials: + +``GATEWAYAPI_BASE_URL`` + Which GatewayAPI platform to use. Optional, defaults to + ``https://gatewayapi.eu``, the platform on which hosting, ownership and + routing stay inside the European Union. Set it to ``https://gatewayapi.com`` + for an account on the global platform. An API token is only valid on the + platform it was created for. + +``BUDGETSMS_SENDER`` + Sender identity to show on the message, at most 11 alphanumeric or 16 + numeric characters. Optional, defaults to ``Challenger``. The BudgetSMS API + requires a sender on every message; the other helpers use the sender + configured on the provider account. Note that an alphanumeric sender has to + be registered with the operator in a number of countries before messages + using it are delivered. + +Only the first three helpers are listed in ``PROVIDERS`` as shipped. The three +below them are operated inside the European Economic Area, which avoids +transferring the phone number and the TAN — personal data that is at the same +time an authentication secret — to a third country, and with it the need for a +transfer instrument under Chapter V of the GDPR. They have been written against +the published specifications of their APIs and are covered by the offline test +suite, but have not yet been exercised against a live account, which is why a +deployment has to enable them explicitly by adding their name to ``PROVIDERS``. + +Whether a failing provider causes the next one to be tried depends on the class +of failure: a number that one provider rejects would be rejected by all of +them, so that is reported immediately, whereas a provider that is down, out of +credit, rate limited or misconfigured does not prevent another from succeeding. +The full table of exit statuses is in challenger-send-sms(1), and each helper's +manual page documents the subset it can report, its API, and its credentials. + +.. warning:: + + A provider that accepts a message charges for it. Because a submission that + times out may still have been accepted, a fall-through can send the same TAN + twice; the dispatcher prefers that over not delivering a TAN at all. + + Legal conditions for using the service --------------------------------------