Skip to main content

tuwunel_service/server_keys/
get.rs

1use std::borrow::Borrow;
2
3use ruma::{
4	CanonicalJsonObject, ServerName, ServerSigningKeyId, api::federation::discovery::VerifyKey,
5	room_version_rules::RoomVersionRules,
6};
7use tuwunel_core::{Err, Result, implement};
8
9use super::{PubKeyMap, PubKeys, extract_key};
10
11#[implement(super::Service)]
12pub async fn get_event_keys(
13	&self,
14	object: &CanonicalJsonObject,
15	version: &RoomVersionRules,
16) -> Result<PubKeyMap> {
17	use ruma::signatures::required_keys;
18
19	let required = match required_keys(object, &version.signatures) {
20		| Ok(required) => required,
21		| Err(e) => {
22			return Err!(BadServerResponse("Failed to determine keys required to verify: {e}"));
23		},
24	};
25
26	let batch = required
27		.iter()
28		.map(|(s, ids)| (s.borrow(), ids.iter().map(Borrow::borrow)));
29
30	Ok(self.get_pubkeys(batch).await)
31}
32
33#[implement(super::Service)]
34pub async fn get_pubkeys<'a, S, K>(&self, batch: S) -> PubKeyMap
35where
36	S: Iterator<Item = (&'a ServerName, K)> + Send,
37	K: Iterator<Item = &'a ServerSigningKeyId> + Send,
38{
39	let mut keys = PubKeyMap::new();
40	for (server, key_ids) in batch {
41		let pubkeys = self.get_pubkeys_for(server, key_ids).await;
42		keys.insert(server.as_str().into(), pubkeys);
43	}
44
45	keys
46}
47
48#[implement(super::Service)]
49pub async fn get_pubkeys_for<'a, I>(&self, origin: &ServerName, key_ids: I) -> PubKeys
50where
51	I: Iterator<Item = &'a ServerSigningKeyId> + Send,
52{
53	let mut keys = PubKeys::new();
54	for key_id in key_ids {
55		if let Ok(verify_key) = self.get_verify_key(origin, key_id).await {
56			keys.insert(key_id.as_str().into(), verify_key.key);
57		}
58	}
59
60	keys
61}
62
63#[implement(super::Service)]
64pub async fn get_verify_key(
65	&self,
66	origin: &ServerName,
67	key_id: &ServerSigningKeyId,
68) -> Result<VerifyKey> {
69	let notary_first = self
70		.services
71		.server
72		.config
73		.query_trusted_key_servers_first;
74
75	let notary_only = self
76		.services
77		.server
78		.config
79		.only_query_trusted_key_servers;
80
81	if let Some(result) = self.verify_keys_for(origin).await.remove(key_id) {
82		return Ok(result);
83	}
84
85	if notary_first
86		&& let Ok(result) = self
87			.get_verify_key_from_notaries(origin, key_id)
88			.await
89	{
90		return Ok(result);
91	}
92
93	if !notary_only
94		&& let Ok(result) = self
95			.get_verify_key_from_origin(origin, key_id)
96			.await
97	{
98		return Ok(result);
99	}
100
101	if !notary_first
102		&& let Ok(result) = self
103			.get_verify_key_from_notaries(origin, key_id)
104			.await
105	{
106		return Ok(result);
107	}
108
109	Err!(BadServerResponse(debug_error!(
110		?key_id,
111		?origin,
112		"Failed to fetch federation signing-key"
113	)))
114}
115
116#[implement(super::Service)]
117async fn get_verify_key_from_notaries(
118	&self,
119	origin: &ServerName,
120	key_id: &ServerSigningKeyId,
121) -> Result<VerifyKey> {
122	for notary in &self.services.config.trusted_servers {
123		if let Ok(server_keys) = self.notary_request(notary, origin).await {
124			for server_key in server_keys.clone() {
125				self.add_signing_keys(server_key).await;
126			}
127
128			for server_key in server_keys {
129				if let Some(result) = extract_key(server_key, key_id) {
130					return Ok(result);
131				}
132			}
133		}
134	}
135
136	Err!(Request(NotFound("Failed to fetch signing-key from notaries")))
137}
138
139#[implement(super::Service)]
140async fn get_verify_key_from_origin(
141	&self,
142	origin: &ServerName,
143	key_id: &ServerSigningKeyId,
144) -> Result<VerifyKey> {
145	if let Ok(server_key) = self.server_request(origin).await {
146		self.add_signing_keys(server_key.clone()).await;
147		if let Some(result) = extract_key(server_key, key_id) {
148			return Ok(result);
149		}
150	}
151
152	Err!(Request(NotFound("Failed to fetch signing-key from origin")))
153}