aboutsummaryrefslogtreecommitdiffstats
path: root/src/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/access')
-rw-r--r--src/access/envelope.rs25
-rw-r--r--src/access/rules.rs1
-rw-r--r--src/access/screen.rs1
-rw-r--r--src/access/sealed.rs3
4 files changed, 27 insertions, 3 deletions
diff --git a/src/access/envelope.rs b/src/access/envelope.rs
index 1804b98..e0c8909 100644
--- a/src/access/envelope.rs
+++ b/src/access/envelope.rs
@@ -108,6 +108,9 @@ fn agree(pattern: &[String], path: &[String]) -> bool {
/// A signed value's payload.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct Payload {
+ /// The swarm it is for: one user, with the same name and key in two swarms, signs
+ /// for one only.
+ pub(crate) swarm: String,
pub(crate) path: Vec<String>,
pub(crate) value: JsonValue,
pub(crate) user: String,
@@ -170,7 +173,7 @@ pub(crate) fn read(envelope: &str) -> Result<Payload, String> {
/// Checks `envelope` as the value at `path`, replacing `previous` (the envelope there
/// before, if any), against the user registry `doc` holds (as the writer saw it): for
-/// that path, naming what it replaces, signed by one of its user's keys, a user who may
+/// its swarm, that path, naming what it replaces, signed by one of its user's keys, a user who may
/// write there.
pub(crate) fn check(
doc: &impl ReadDoc,
@@ -179,6 +182,15 @@ pub(crate) fn check(
previous: Option<&str>,
) -> Result<Signed, String> {
let (bytes, payload, signature) = open(envelope)?;
+ let swarm = store::read_path(
+ doc,
+ &crate::document::meta::path(&[crate::document::meta::SWARM]),
+ )
+ .ok()
+ .flatten();
+ if swarm.as_ref().and_then(JsonValue::as_str) != Some(payload.swarm.as_str()) {
+ return Err(format!("signed for swarm {}, not this one", payload.swarm));
+ }
if payload.path != path {
return Err(format!(
"signed for /{}, not /{}",
@@ -223,6 +235,7 @@ mod tests {
let line = sshsig::PublicKey(key.verifying_key().to_bytes()).line();
let mut doc = Document::new();
change(&mut doc, |doc| {
+ store::write_path(doc, &path("_continuum/swarm"), &json!("s")).unwrap();
let mut alice = registry::entry("root", 1, &[(path("config"), &[Right::Write][..])]);
alice["keys"] = json!({ "laptop": line });
store::write_path(doc, &registry::user_path("alice"), &alice).unwrap();
@@ -240,6 +253,7 @@ mod tests {
fn payload(user: &str, at: &str, value: JsonValue, prev: &str) -> Payload {
Payload {
+ swarm: "s".to_owned(),
path: path(at),
value,
user: user.to_owned(),
@@ -282,6 +296,15 @@ mod tests {
let tampered = first.replacen("cv1.", "cv1.e30", 1);
assert!(check(&doc, &tampered, &path("config"), None).is_err());
assert!(check(&doc, "plain", &path("config"), None).is_err());
+ // For another swarm.
+ let elsewhere = signed(
+ &key,
+ &Payload {
+ swarm: "t".to_owned(),
+ ..payload("alice", "config", json!({"mode": "fast"}), "")
+ },
+ );
+ assert!(check(&doc, &elsewhere, &path("config"), None).is_err());
}
#[test]
diff --git a/src/access/rules.rs b/src/access/rules.rs
index a56e5ae..3eca1c9 100644
--- a/src/access/rules.rs
+++ b/src/access/rules.rs
@@ -888,6 +888,7 @@ mod tests {
);
let sealed = |at: &str, prev: &str| {
let payload = envelope::Payload {
+ swarm: "s".to_owned(),
path: path(at),
value: json!({"mode": "fast"}),
user: "alice".to_owned(),
diff --git a/src/access/screen.rs b/src/access/screen.rs
index 4c640b6..aa16b42 100644
--- a/src/access/screen.rs
+++ b/src/access/screen.rs
@@ -761,6 +761,7 @@ mod tests {
write(&mut theirs, "a", None, "_continuum/members/a", json!({}));
let sealed = |prev: &str, value: serde_json::Value| {
let payload = envelope::Payload {
+ swarm: "s".to_owned(),
path: path("config"),
value,
user: "alice".to_owned(),
diff --git a/src/access/sealed.rs b/src/access/sealed.rs
index 7a8896f..ed5024c 100644
--- a/src/access/sealed.rs
+++ b/src/access/sealed.rs
@@ -347,8 +347,7 @@ mod tests {
assert!(check(&doc, notes, &json!("plain")).is_err());
// Signed: holding a sealed value, or null.
let signed = |value: JsonValue| {
- let payload =
- json!({"path": ["notes"], "value": value, "user": "alice", "at": 1, "prev": ""});
+ let payload = json!({"swarm": "s", "path": ["notes"], "value": value, "user": "alice", "at": 1, "prev": ""});
format!("cv1.{}.c2ln", B64URL.encode(payload.to_string()))
};
assert!(check(&doc, notes, &json!(signed(json!(sealed_for(&[key(9)]))))).is_ok());