fix: deliver an accept token once, not on every message
send attached the token to every message addressed to an accepted correspondent, so a secret rode in the body of ordinary mail indefinitely. sec 5.8 says the owner delivers each token to its correspondent; it does not say every message carries one. Harmless between people, and fatal for any recipient that republishes what it receives: a published record is verified by rebuilding the exact bytes the author signed, and those cannot include a token without disclosing it. An author who accepted such a service could never post to it again — and accepting a correspondent is the behaviour the rest of the system teaches. Schema 3 adds `delivered`, set only once the recipient's server has taken the message, so a failed send leaves the token still owing. Not cleared by block: the token is a pure function of the master and the identity frozen at acceptance, so they keep the value either way and re-accepting hands back the same one. Existing rows migrate as still owing rather than delivered. One more message carries the token, which is what every message did before, so nothing that works today can break; assuming delivery would instead strand anyone accepted but never written to.
This commit is contained in:
parent
8872ec6c98
commit
16dafcd388
2 changed files with 121 additions and 4 deletions
|
|
@ -529,8 +529,13 @@ pub fn send(
|
|||
fields.push(("Reply-To".into(), home.uri(&me.pk())));
|
||||
}
|
||||
}
|
||||
// sec 5.8: hand an accepted correspondent the token for our own mailbox.
|
||||
if let Some(identity) = store.accepted_identity(&addr.short())? {
|
||||
// sec 5.8: hand an accepted correspondent the token for our own mailbox —
|
||||
// once. Re-attaching it to every later message put a secret in the body of
|
||||
// ordinary mail, and a recipient that republishes what it receives cannot
|
||||
// carry one: a published record is verified by rebuilding the exact signed
|
||||
// bytes, and the token must not be among them.
|
||||
let deliver_to = store.token_to_deliver(&addr.short())?;
|
||||
if let Some(identity) = deliver_to {
|
||||
fields.push(("Accept".into(), b32(&account.token_for(&identity))));
|
||||
}
|
||||
let borrowed: Vec<(&str, &str)> = fields
|
||||
|
|
@ -567,6 +572,12 @@ pub fn send(
|
|||
None
|
||||
};
|
||||
|
||||
// Only now, with the message accepted by their server: a send that failed
|
||||
// earlier leaves the token still owing, so the next attempt carries it.
|
||||
if deliver_to.is_some() {
|
||||
store.mark_delivered(&addr.short())?;
|
||||
}
|
||||
|
||||
// sec 5.6: the ephemeral is gone, so keep a copy sealed to ourselves.
|
||||
store.store_sent(&mid, &addr.short(), &self_copy, now())?;
|
||||
Ok(Sent {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue