85.1.58. pepsi-helper-auto-pay¶
drive taler-wallet-cli as the paying user
- Manual section:
1
85.1.58.1.1. Name¶
pepsi-helper-auto-pay - privileged helper that prices or pays a GNU Taler
delivery demand by running taler-wallet-cli as the right user.
85.1.58.1.2. Synopsis¶
pepsi-helper-auto-pay OP ( –uid N | –user NAME –wallet-db KEY ) [–wallet-cli PATH] [OP-OPTIONS]
where OP is one of preview/pay –uri TALER-URI [–pay-option OPT]…, balance, withdraw –amount CURRENCY:VALUE –exchange URL, push –uri TALER-URI, or pull –amount CURRENCY:VALUE [–subject TEXT].
85.1.58.1.3. Description¶
pepsi-helper-auto-pay is a minimal, security-hardened helper that runs
taler-wallet-cli against exactly one wallet, as exactly one user, for one wallet
operation. It exists so that a trusted but unprivileged caller (a member of the
pepsi-wallets group, in practice pepsi-stage-auto-pay(1)) can drive the
appropriate wallet — and do nothing else.
The supported operations are: preview (price a taler://pay/… demand without
paying) and pay (settle one) for the inbound demand-paying role; and balance,
withdraw (set up a manual top-up against an exchange), push (accept an
incoming taler://pay-push/… peer payment) and pull (initiate a peer pull,
producing a taler://pay-pull/… URI) for the wallet self-service role.
The helper is installed setuid-root, owned root:pepsi-wallets with mode
4750. Only members of the pepsi-wallets group may execute it; when they
do, the kernel runs it with an effective uid of root. The helper then:
resolves the target account and, in shared mode, the wallet-database path inside that account’s home built from the validated KEY (the path can therefore never escape the home);
fully and irreversibly drops privilege to the target user — installs the user’s supplementary groups, then sets the gid, then the uid (real+effective+saved), verifying root cannot be regained — refusing uid
0and the loginroot. In local-user mode it additionally refuses any uid below/etc/login.defsUID_MIN(1000 when that file cannot be read; a real recipient is expected there); shared mode is exempt, since its target is the operator-configuredWALLET_USERservice account (e.g.pepsi-wallets, typically a low uid). (Like pepsi-helper-dot-forward(1) and pepsi-helper-maildir-writer(1), it sheds root completely.)execs
taler-wallet-cli— optionally with--wallet-db=…— for the requested operation, with an environment built from scratch, not filtered: the child gets onlyHOME,USER/LOGNAME(the target account), a fixedPATHandSHELL, and nothing the caller passed in. Privilege has already been dropped, so the dynamic loader honoursLD_PRELOAD/LD_AUDITagain, and the wallet is a Node.js program that honoursNODE_OPTIONS/NODE_PATH; every variable in the caller’s environment is caller-chosen, so subtracting known-bad names would leave “run the wallet as alice” reachable as “run the caller’s code as alice” — the escalation this helper exists to prevent — and would also let the caller redirect the wallet’s exchange traffic (https_proxy/SSL_CERT_FILE). In shared mode the wallet-database directory~NAME/walletsis created mode0700if absent.previewasks wallet-core for the proposal (api preparePayForUri) and reads the price out of the contract terms —handle-uricannot be used to quote, since without--yesit stops at a confirmation prompt that does not end on EOF, and prints no price anyway.payrunshandle-uri --choice-index 0 --yesplus any extra--pay-optionarguments and runs to completion (a version-1 contract offers a list ofchoicesand cannot be paid until one is named; the first is the onepreviewpriced).pushtakes two wallet commands —p2p prepare-push-creditfor the incoming payment’s transaction id, thenp2p confirm-push-creditto accept it (handle-uridoes not return for such a URI, so the purse would expire unaccepted).balance,withdrawandpullrun the corresponding wallet subcommands and report their result (the balance text, the withdrawal wire instructions, or the pay-pull URI). The exacttaler-wallet-clisubcommands are the one wallet-version-dependent point, isolated in the helper.
After a pull, and after accepting a push, the helper runs the wallet’s
task loop (run-until-done) for a bounded time (30 seconds). p2p
initiate-pull-credit only records the request locally, and the purse is created
at the exchange by that loop — until it has run, the URI the user is sent is not
payable at all, and nothing else would ever run it, since a per-user wallet only
wakes up when its owner sends the next command. The bound exists because a
peer-pull credit is not “done” until somebody pays it, so the command would
otherwise wait forever.
If the wallet reports a KYC (identity verification) requirement for a self-service operation, the helper extracts the KYC URL and exits 3 with the URL on standard output, so the stage can e-mail the link to the user. This is considered only when the operation produced no result of its own: an operation that succeeded is reported as a success even if the wallet’s diagnostic output mentions KYC somewhere, and the URL is taken from the text that mentions it rather than from wherever a URL first appears.
The two account models are selected by the caller. With –uid the helper drops
to that local uid and uses that user’s default wallet (WALLET_MODE = local-user
in pepsi-stage-auto-pay(1)). With –user and –wallet-db it drops to
the named shared account (default pepsi-wallets) and points the wallet at
~NAME/wallets/KEY.sqlite3 (WALLET_MODE = shared).
This program is not meant to be run by hand; pepsi-stage-auto-pay(1) invokes it. It is documented here because of its privileged installation.
85.1.58.1.4. Options¶
- preview | pay | balance | withdraw | push | pull
The operation.
previewprints a demand’s price without paying;paysettles it;balanceprints the wallet balance;withdrawsets up a manual top-up and prints the wire instructions;pushaccepts an incoming peer payment;pullinitiates a peer pull and prints the resulting URI.- –uri TALER-URI
The
taler://pay/…(preview/pay) ortaler://pay-push/…(push) URI to act on. Required for those operations. It is re-validated here, at the privileged edge:preview/payrefuse anything that is not ataler://pay/URI,pushanything that is nottaler://, and any URI is refused outright if it holds a character outside the RFC 3986 repertoire (so quotes, backslashes and whitespace can never reach the wallet).- –amount CURRENCY:VALUE
The GNU Taler amount, required for
withdrawandpull.- –exchange URL
The exchange base URL for a manual
withdraw(required).- –subject TEXT
An optional payment subject/summary for
pull.- –uid N
Local-user mode: drop to uid N and use that user’s default wallet. Mutually exclusive with –user.
- –user NAME –wallet-db KEY
Shared mode: drop to account NAME and use the wallet database named by the opaque, validated KEY under that account’s home. Both are required together.
- –wallet-cli PATH
The
taler-wallet-clibinary to run (defaulttaler-wallet-cli, resolved on$PATH).- –pay-option OPT
An extra argument appended to the
payinvocation (repeatable, e.g.--run-until-done);--yesis added topayas well, since a helper run from a stage has nobody to ask.Neither applies to push, which is not a
handle-uricall at all but a two-commandp2p prepare-push-credit/confirm-push-creditflow:confirm-push-creditrejects those flags outright, and the task loop they usually ask for is what the helper’s own drive loop does anyway. The options are accepted and ignored on that path, so aWALLET_PAY_OPTIONSset for a self-servicepushhas no effect.
85.1.58.1.5. Exit Status¶
- 0
Success. For
previewthe proposed amount is on standard output; forbalance,withdrawandpullthe report text is on standard output; forpayandpushstandard output is empty.- 2
The operation failed (bad arguments, not setuid-root, a refused account, the price could not be read, or the wallet operation failed). A human-readable diagnostic is written to standard output and standard error.
- 3
The wallet requires KYC (identity verification); the KYC URL is on standard output.
85.1.58.1.6. Security¶
The helper deliberately does no configuration, database or logging work. Its only
privileged action is to become the target user before running the wallet; it
refuses to act as root and verifies root is unrecoverable after dropping
privilege. Access to it is gated by the pepsi-wallets group, granted to the
caller through pepsi-stage-auto-pay(1)’s SGID bit and to no one else.
85.1.58.1.7. See Also¶
pepsi-stage-auto-pay(1), pepsi-stage-anti-spam(1), pepsi-helper-dot-forward(1), pepsi-dispatch(1), pepsi.conf(5)
85.1.58.1.8. Bugs¶
Report bugs to the Pepsi issue tracker.