aboutsummaryrefslogtreecommitdiffstats
path: root/rs/common
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-01-22 22:52:01 +0100
committerLibravatar Rutger Broekhoff2024-01-22 22:52:01 +0100
commitf5ff2803af0e03f57ab3093a9384d91abb9de083 (patch)
treeedb5a5c28c183c421bdf2b3e2c05c36ecb77bacd /rs/common
parentefe9d55ea6c01c718d3c53dbcee6b48899b48267 (diff)
downloadgitolfs3-f5ff2803af0e03f57ab3093a9384d91abb9de083.tar.gz
gitolfs3-f5ff2803af0e03f57ab3093a9384d91abb9de083.zip
Finish basic implementation of Rust LFS server
Diffstat (limited to 'rs/common')
-rw-r--r--rs/common/src/lib.rs43
1 files changed, 33 insertions, 10 deletions
diff --git a/rs/common/src/lib.rs b/rs/common/src/lib.rs
index aafe7f1..27205bd 100644
--- a/rs/common/src/lib.rs
+++ b/rs/common/src/lib.rs
@@ -37,8 +37,9 @@ impl FromStr for Operation {
37} 37}
38 38
39#[repr(u8)] 39#[repr(u8)]
40pub enum AuthType { 40enum AuthType {
41 GitLfsAuthenticate = 1, 41 BatchApi = 1,
42 Download = 2,
42} 43}
43 44
44/// None means out of range. 45/// None means out of range.
@@ -156,6 +157,12 @@ impl<const N: usize> SafeByteArray<N> {
156 } 157 }
157} 158}
158 159
160impl<const N: usize> Default for SafeByteArray<N> {
161 fn default() -> Self {
162 Self::new()
163 }
164}
165
159impl<const N: usize> AsRef<[u8]> for SafeByteArray<N> { 166impl<const N: usize> AsRef<[u8]> for SafeByteArray<N> {
160 fn as_ref(&self) -> &[u8] { 167 fn as_ref(&self) -> &[u8] {
161 &self.inner 168 &self.inner
@@ -184,10 +191,18 @@ impl<const N: usize> FromStr for SafeByteArray<N> {
184 } 191 }
185} 192}
186 193
194pub type Oid = Digest<32>;
195
196#[derive(Debug, Copy, Clone)]
197pub enum SpecificClaims {
198 BatchApi(Operation),
199 Download(Oid),
200}
201
202#[derive(Debug, Copy, Clone)]
187pub struct Claims<'a> { 203pub struct Claims<'a> {
188 pub auth_type: AuthType, 204 pub specific_claims: SpecificClaims,
189 pub repo_path: &'a str, 205 pub repo_path: &'a str,
190 pub operation: Operation,
191 pub expires_at: DateTime<Utc>, 206 pub expires_at: DateTime<Utc>,
192} 207}
193 208
@@ -198,10 +213,18 @@ pub fn generate_tag(claims: Claims, key: impl AsRef<[u8]>) -> Option<Digest<32>>
198 } 213 }
199 214
200 let mut hmac = hmac_sha256::HMAC::new(key); 215 let mut hmac = hmac_sha256::HMAC::new(key);
201 hmac.update([claims.auth_type as u8]); 216 match claims.specific_claims {
217 SpecificClaims::BatchApi(operation) => {
218 hmac.update([AuthType::BatchApi as u8]);
219 hmac.update([operation as u8]);
220 }
221 SpecificClaims::Download(oid) => {
222 hmac.update([AuthType::Download as u8]);
223 hmac.update(oid.as_bytes());
224 }
225 }
202 hmac.update([claims.repo_path.len() as u8]); 226 hmac.update([claims.repo_path.len() as u8]);
203 hmac.update(claims.repo_path.as_bytes()); 227 hmac.update(claims.repo_path.as_bytes());
204 hmac.update([claims.operation as u8]);
205 hmac.update(claims.expires_at.timestamp().to_be_bytes()); 228 hmac.update(claims.expires_at.timestamp().to_be_bytes());
206 Some(hmac.finalize().into()) 229 Some(hmac.finalize().into())
207} 230}
@@ -280,9 +303,9 @@ impl<const N: usize> From<[u8; N]> for Digest<N> {
280 } 303 }
281} 304}
282 305
283impl<const N: usize> Into<[u8; N]> for Digest<N> { 306impl<const N: usize> From<Digest<N>> for [u8; N] {
284 fn into(self) -> [u8; N] { 307 fn from(val: Digest<N>) -> Self {
285 self.inner 308 val.inner
286 } 309 }
287} 310}
288 311
@@ -304,7 +327,7 @@ impl<const N: usize> ConstantTimeEq for Digest<N> {
304 327
305impl<const N: usize> PartialEq for Digest<N> { 328impl<const N: usize> PartialEq for Digest<N> {
306 fn eq(&self, other: &Self) -> bool { 329 fn eq(&self, other: &Self) -> bool {
307 self.ct_eq(&other).into() 330 self.ct_eq(other).into()
308 } 331 }
309} 332}
310 333