85.1.38. pepsi-stage-secure-link¶

hold a message that could not be encrypted, and mail the link

Manual section:

1

85.1.38.1.1. Name¶

pepsi-stage-secure-link - the secure-link fallback stage of the Pepsi pipeline.

85.1.38.1.2. Synopsis¶

pepsi-stage-secure-link [GLOBAL-OPTIONS] worker

85.1.38.1.3. Description¶

pepsi-stage-secure-link is a stage program run by pepsi-dispatch(1) as a persistent worker reading message ids on standard input.

It is the far end of [stage-encrypt] ON_NO_KEY = secure-link. When pepsi-stage-encrypt(1) must encrypt a message and the recipient publishes no usable key, it routes the message here instead of sending it in the clear or bouncing it. This stage then takes the message off the wire entirely:

  1. it generates a PIN, derives the URL token from the queue row (see Retries) and a content key from the PIN and the server-side pepper, and seals the whole message under it;

  2. in one transaction it stores only the AEAD ciphertext in pepsi.secure_message and queues a notification mail to the recipient carrying the link, and — under the default PIN_DELIVERY = sender — a second mail to the sender carrying the PIN, for the sender to relay by telephone or text message;

  3. it deletes the queue row.

The row is deleted rather than advanced because advancing it would transmit the cleartext to the very recipient who must not receive cleartext. The message’s continuation is the notification, which is an ordinary outbound message injected at [pepsi-secure-link] NOTIFY_STAGE and signed and relayed like any other. The stage is therefore terminal and has no NEXT_STAGE.

A message with several keyless recipients produces one stored message per recipient, each with its own token, PIN and ciphertext, so one recipient’s PIN never opens another’s copy and the recipient list is not disclosed to any of them.

85.1.38.1.4. Configuration¶

The stage’s [stage-<name>] section carries only PROGRAM. Everything else lives in the global [pepsi-secure-link] section (see pepsi.conf(5)), deliberately: the expiry window, the PIN length and the lockout are not behavioural knobs a correspondent may edit by e-mail through pepsi-stage-edit-settings(1), and a global section is out of reach of the per-address override layer.

85.1.38.1.5. Example¶

[stage-encrypt]
PROGRAM = pepsi-stage-encrypt
ENCRYPT = required
SECURE_LINK_STAGE = secure-link
NEXT_STAGE = srs

[stage-secure-link]
PROGRAM = pepsi-stage-secure-link

[pepsi-secure-link]
BASE_URL = https://secure.example.org
NOTIFY_STAGE = srs
# PEPPER is written to secrets.d/pepsi-secure-link.secret by pepsi-setup.

85.1.38.1.6. Retries¶

A stage body can run more than once for the same queue row: a worker that dies after its side effects but before the commit, a pepsi-dispatch(1) restart re-claiming a running row, an operator requeue, and a failure part-way through, which is retried (see Failure). The per-recipient loop is not atomic — a failure at the k-th recipient leaves every recipient before it already stored and notified — but each recipient is: the stored copy and its notifications are committed together, by one call of the secure_message_store SQL function, or not at all.

So the secure-message token is derived from the queue row, as a keyed hash of the row’s token and the recipient’s position under the deployment’s PEPPER, rather than drawn at random. A repeated pass recomputes the same token, finds that recipient’s pepsi.secure_message row already present, logs a warning and leaves it alone: no second copy, no second link to the recipient and no second PIN to the sender. The token is keyed rather than merely hashed because it is the link URL — anything an outsider could recompute would be a link they could guess.

Only the token is derived. The PIN stays random on every pass and is stored nowhere, which is the property that makes a stolen database and even a stolen server useless (see pepsi-secure-link(1)); a PIN reproducible from the pepper and the row’s token would be one the operator could recompute. That is why the copy and its announcement must be one commit: a copy stored without its notifications would carry a PIN that no longer exists anywhere, and no retry could announce it. As it is, a stored copy is always an announced one, and a retry that finds it has nothing left to do for that recipient.

The one thing a retry can repeat is PIN_DELIVERY = command: the command runs before the commit (so a gateway that is down leaves nothing stored), and if the commit then fails, the next pass sends a new PIN; the earlier one opens nothing, since nothing was stored under it.

85.1.38.1.7. Failure¶

Everything that can fail is done before the queue row is deleted, and nothing that fails ever sends the message on: a message that reached this stage is by definition one the operator said must not go out unprotected.

  • A [pepsi-secure-link] section that does not parse, has no BASE_URL or PEPPER (or a pepper that cannot be read), or no NOTIFY_STAGE makes the worker refuse to start (exit 78): the dispatcher holds the queue until the configuration is fixed, instead of each message failing on its own.

  • A fault of this host — a notification template that cannot be read, PIN_DELIVERY = command failing to start, failing or not finishing within 30 seconds, the database — is retried, after one minute and then at doubling intervals up to an hour, until the message has been queued longer than the stage’s MAX_LIFETIME (default 120 h); then it goes to the stage’s BOUNCE_STAGE, or is failed without one (see pepsi-dispatch(1)).

  • A message with the null envelope sender is failed at once: there would be nobody to give the PIN to.

85.1.38.1.8. Exit status¶

The worker exits 0 on a clean end of input, and 78 when it refuses to start because [pepsi-secure-link] is not usable (see Failure). Per-message failure is reported through the queue, not the exit status.

85.1.38.1.9. See also¶

pepsi-secure-link(1), pepsi-stage-encrypt(1), pepsi-httpd(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7)

Logo

Pepsi 0.0.0

Languages

  • English
  • Deutsch
  • français

Navigation

Contents

  • 1. Introduction
  • 2. Getting started on a cheap VPS
  • 3. Installation
  • 4. Debian packages
  • 5. The Wizard
  • 6. Configuration
  • 7. Operating Pepsi
  • 8. Troubleshooting
  • 9. Supported Features
  • 10. SMTP Protocol Extensions
  • 11. Key management
  • 12. The secure-link fallback portal
  • 13. Client interoperability
  • 14. Threat model
  • 15. Security model
  • 16. Microsoft Exchange as a gateway
  • 17. Mailing lists
  • 18. Archives
  • 19. The GNU Mailman 3 REST API
  • 20. The administrative API
  • 21. The administration console
  • 22. Architecture
  • 23. The message state
  • 24. Extending the Pipeline
  • 25. Test Suite
  • 26. Benchmark Suite
  • 27. Performance
  • 28. pepsi-ingress
  • 29. pepsi-dispatch
  • 30. pepsi-httpd
  • 31. pepsi-stage-arc
  • 32. pepsi-stage-srs
  • 33. pepsi-stage-encrypt
  • 34. pepsi-stage-decrypt
  • 35. pepsi-stage-dkim-sign
  • 36. pepsi-stage-bounce
  • 37. pepsi-stage-aliases
  • 38. pepsi-stage-relay-to-internet
  • 39. pepsi-stage-relay-to-smarthost
  • 40. pepsi-stage-relay-to-maildir
  • 41. pepsi-stage-dot-forward
  • 42. pepsi-stage-relay-to-lmtp
  • 43. pepsi-stage-discard
  • 44. pepsi-stage-anti-spam
  • 45. pepsi-stage-auto-pay
  • 46. pepsi-stage-check-whitelist
  • 47. pepsi-stage-auto-whitelist
  • 48. pepsi-stage-autocrypt-learn
  • 49. pepsi-stage-reencrypt
  • 50. pepsi-stage-detect-language
  • 51. pepsi-detect-language
  • 52. pepsi-stage-block-language
  • 53. pepsi-stage-vacation
  • 54. pepsi-stage-secretary
  • 55. pepsi-stage-edit-settings
  • 56. pepsi-stage-if
  • 57. pepsi-stage-milter
  • 58. pepsi-stage-route
  • 59. pepsi-stage-vks-confirm
  • 60. pepsi-stage-secure-link
  • 61. pepsi-setup
  • 62. pepsi-queue
  • 63. pepsi-status
  • 64. pepsi-sendmail
  • 65. pepsi-whitelist
  • 66. pepsi-keys
  • 67. pepsi-keydisc
  • 68. pepsi-settings
  • 69. pepsi-list
  • 70. pepsi-archive
  • 71. pepsi-stage-list
  • 72. pepsi-stage-list-post
  • 73. pepsi-stage-list-deliver
  • 74. pepsi-stage-list-command
  • 75. pepsi-stage-list-bounce
  • 76. pepsi-tlsrpt
  • 77. pepsi-secure-link
  • 78. pepsi-failure-bouncer
  • 79. pepsi-quota
  • 80. pepsi-helper-token-refresh
  • 81. pepsi-telemetry
  • 82. pepsi-telemetry-client
  • 83. pepsi-config
  • 84. Feature stability
  • 85. Manual pages
    • 85.1. Commands (section 1)
    • 85.2. Configuration file (section 5)
    • 85.3. Message state (section 7)
  • 86. RFC Index

Related Topics

  • Documentation overview
    • 85. Manual pages
      • Previous: 85.1.37. pepsi-stage-vks-confirm
      • Next: 85.1.39. pepsi-setup

Quick search

©2026, GNUnet e.V.. | Powered by Sphinx 8.1.3 & Alabaster 0.7.16 | Page source