JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Add all the user request handling

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨e3bda14

⁨src/messages/mod.rs⁩ - ⁨7925⁩ bytes
Raw
1 use anyhow::Error;
2 use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation};
3 use rsa::{
4 pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey},
5 pss::{Signature, SigningKey, VerifyingKey},
6 sha2::Sha256,
7 signature::{RandomizedSigner, SignatureEncoding, Verifier},
8 RsaPrivateKey, RsaPublicKey,
9 };
10 use serde::{Deserialize, Serialize};
11 use std::fmt::Debug;
12
13 use crate::{
14 authentication::UserTokenMetadata,
15 handshake::HandshakeMessage,
16 model::{instance::Instance, user::User},
17 };
18
19 use self::{
20 authentication::AuthenticationMessage, discovery::DiscoveryMessage,
21 repository::RepositoryMessage, user::UserMessage,
22 };
23
24 pub mod authentication;
25 pub mod discovery;
26 pub mod issues;
27 pub mod repository;
28 pub mod user;
29
30 #[derive(Clone, Serialize, Deserialize)]
31 pub enum MessageKind {
32 Handshake(HandshakeMessage),
33 Repository(RepositoryMessage),
34 Authentication(AuthenticationMessage),
35 Discovery(DiscoveryMessage),
36 User(UserMessage),
37 }
38
39 /// An authenticated message, where the instance is authenticating
40 /// a request it is making for itself.
41 #[derive(Serialize, Deserialize)]
42 pub struct InstanceAuthenticated<T: Serialize> {
43 message: T,
44 pub instance: Instance,
45 signature: Vec<u8>,
46 }
47
48 impl<T> PartialEq for InstanceAuthenticated<T>
49 where
50 T: PartialEq + Serialize,
51 {
52 fn eq(&self, other: &Self) -> bool {
53 self.message == other.message
54 && self.instance == other.instance
55 && self.signature == other.signature
56 }
57 }
58
59 impl<T> Eq for InstanceAuthenticated<T> where T: Eq + Serialize {}
60
61 impl<T> std::hash::Hash for InstanceAuthenticated<T>
62 where
63 T: std::hash::Hash + Serialize,
64 {
65 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
66 self.message.hash(state);
67 self.instance.hash(state);
68 self.signature.hash(state);
69 }
70 }
71
72 impl<T> Clone for InstanceAuthenticated<T>
73 where
74 T: Clone + Serialize,
75 {
76 fn clone(&self) -> Self {
77 Self {
78 message: self.message.clone(),
79 instance: self.instance.clone(),
80 signature: self.signature.clone(),
81 }
82 }
83 }
84
85 impl<T> Debug for InstanceAuthenticated<T>
86 where
87 T: Debug + Serialize,
88 {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.debug_struct("Authenticated")
91 .field("message", &self.message)
92 .field("instance", &self.instance)
93 .field("signature", &self.signature)
94 .finish()
95 }
96 }
97
98 impl<T: Serialize> InstanceAuthenticated<T> {
99 pub fn new(message: T, instance: Instance, private_key: String) -> Result<Self, Error> {
100 let mut rng = rand::thread_rng();
101
102 let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?;
103 let signing_key = SigningKey::<Sha256>::new(private_key);
104
105 let message_json = serde_json::to_vec(&message)?;
106
107 let signature = signing_key.sign_with_rng(&mut rng, &message_json);
108
109 Ok(Self {
110 message,
111 instance,
112 signature: signature.to_vec(),
113 })
114 }
115
116 pub async fn inner(&self) -> &T {
117 &self.message
118 }
119
120 pub async fn validate(&self, instance: &Instance) -> Result<(), Error> {
121 let public_key = public_key(instance).await?;
122 let public_key = RsaPublicKey::from_pkcs1_pem(&public_key).unwrap();
123
124 let verifying_key: VerifyingKey<Sha256> = VerifyingKey::new(public_key);
125
126 let message_json = serde_json::to_vec(&self.message).unwrap();
127
128 verifying_key
129 .verify(
130 &message_json,
131 &Signature::try_from(self.signature.as_ref()).unwrap(),
132 )
133 .unwrap();
134
135 Ok(())
136 }
137 }
138
139 /// An authenticated message.
140 ///
141 /// Includes the message, with a digest generated with
142 /// our private key.
143 #[derive(Serialize, Deserialize)]
144 pub struct ValidatedUserAuthenticated<T: Serialize> {
145 #[serde(flatten)]
146 message: T,
147 pub(crate) user: User,
148 }
149
150 impl<T> Clone for ValidatedUserAuthenticated<T>
151 where
152 T: Clone + Serialize,
153 {
154 fn clone(&self) -> Self {
155 Self {
156 message: self.message.clone(),
157 user: self.user.clone(),
158 }
159 }
160 }
161
162 impl<T> Debug for ValidatedUserAuthenticated<T>
163 where
164 T: Debug + Serialize,
165 {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 f.debug_struct("Authenticated")
168 .field("message", &self.message)
169 .field("user", &self.user)
170 .finish()
171 }
172 }
173
174 impl<T: Serialize> ValidatedUserAuthenticated<T> {
175 pub async fn inner(&self) -> &T {
176 &self.message
177 }
178
179 pub async fn user(&self) -> &User {
180 &self.user
181 }
182 }
183
184 /// An unvalidated authenticated message.
185 ///
186 /// Includes the message, with a digest generated with
187 /// our private key.
188 #[derive(Serialize, Deserialize)]
189 pub struct UnvalidatedUserAuthenticated<T: Serialize> {
190 #[serde(flatten)]
191 message: T,
192 token: String,
193 digest: Vec<u8>,
194 }
195
196 impl<T> Clone for UnvalidatedUserAuthenticated<T>
197 where
198 T: Clone + Serialize,
199 {
200 fn clone(&self) -> Self {
201 Self {
202 message: self.message.clone(),
203 token: self.token.clone(),
204 digest: self.digest.clone(),
205 }
206 }
207 }
208
209 impl<T> Debug for UnvalidatedUserAuthenticated<T>
210 where
211 T: Debug + Serialize,
212 {
213 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
214 f.debug_struct("Authenticated")
215 .field("message", &self.message)
216 .field("token", &self.token)
217 .field("digest", &self.digest)
218 .finish()
219 }
220 }
221
222 impl<T: Serialize> UnvalidatedUserAuthenticated<T> {
223 pub fn new(message: T, token: String, private_key: String) -> Result<Self, Error> {
224 let mut rng = rand::thread_rng();
225
226 let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key)?;
227 let signing_key = SigningKey::<Sha256>::new(private_key);
228
229 let message_json = serde_json::to_vec(&message)?;
230
231 let signature = signing_key.sign_with_rng(&mut rng, &message_json);
232
233 Ok(Self {
234 message,
235 token,
236 digest: signature.to_vec(),
237 })
238 }
239
240 pub async fn inner(&self) -> &T {
241 &self.message
242 }
243
244 pub async fn validate(self) -> Result<ValidatedUserAuthenticated<T>, Error> {
245 let instance = {
246 let mut validation = Validation::new(Algorithm::RS256);
247 validation.insecure_disable_signature_validation();
248
249 info!("Value: {:?}", self.token);
250
251 let value: TokenData<UserTokenMetadata> =
252 decode(&self.token, &DecodingKey::from_secret(b"test"), &validation).unwrap();
253
254 value.claims.generated_for.clone()
255 };
256
257 let public_key_raw = public_key(&instance).await?;
258 let public_key = RsaPublicKey::from_pkcs1_pem(&public_key_raw).unwrap();
259
260 let verifying_key: VerifyingKey<Sha256> = VerifyingKey::new(public_key);
261
262 let message_json = serde_json::to_vec(&self.message).unwrap();
263
264 verifying_key
265 .verify(
266 &message_json,
267 &Signature::try_from(self.digest.as_ref()).unwrap(),
268 )
269 .unwrap();
270
271 let verification_key = DecodingKey::from_rsa_pem(public_key_raw.as_bytes()).unwrap();
272
273 let data: TokenData<UserTokenMetadata> = decode(
274 &self.token,
275 &verification_key,
276 &Validation::new(Algorithm::RS256),
277 )
278 .unwrap();
279
280 assert_eq!(data.claims.generated_for, instance);
281
282 Ok(ValidatedUserAuthenticated {
283 message: self.message,
284 user: data.claims.user,
285 })
286 }
287 }
288
289 async fn public_key(instance: &Instance) -> Result<String, Error> {
290 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
291 .await?
292 .text()
293 .await?;
294
295 Ok(key)
296 }
297