diff options
-rw-r--r-- | rs/common/src/lib.rs | 16 | ||||
-rw-r--r-- | rs/server/src/main.rs | 45 |
2 files changed, 42 insertions, 19 deletions
diff --git a/rs/common/src/lib.rs b/rs/common/src/lib.rs index 27205bd..89c3286 100644 --- a/rs/common/src/lib.rs +++ b/rs/common/src/lib.rs | |||
@@ -136,9 +136,9 @@ fn parse_hex_exact(value: &str, buf: &mut [u8]) -> Result<(), ParseHexError> { | |||
136 | for (i, c) in value.bytes().enumerate() { | 136 | for (i, c) in value.bytes().enumerate() { |
137 | if let Some(b) = decode_nibble(c) { | 137 | if let Some(b) = decode_nibble(c) { |
138 | if i % 2 == 0 { | 138 | if i % 2 == 0 { |
139 | buf[i / 2] |= b; | 139 | buf[i / 2] |= b << 4; |
140 | } else { | 140 | } else { |
141 | buf[i / 2] = b << 4; | 141 | buf[i / 2] |= b; |
142 | } | 142 | } |
143 | } else { | 143 | } else { |
144 | return Err(ParseHexError::InvalidCharacter); | 144 | return Err(ParseHexError::InvalidCharacter); |
@@ -236,8 +236,16 @@ impl<B: AsRef<[u8]>> fmt::Display for HexFmt<B> { | |||
236 | let HexFmt(buf) = self; | 236 | let HexFmt(buf) = self; |
237 | for b in buf.as_ref() { | 237 | for b in buf.as_ref() { |
238 | let (high, low) = (b >> 4, b & 0xF); | 238 | let (high, low) = (b >> 4, b & 0xF); |
239 | let highc = if high < 10 { b'0' + high } else { b'a' + high }; | 239 | let highc = if high < 10 { |
240 | let lowc = if low < 10 { b'0' + low } else { b'a' + low }; | 240 | high + b'0' |
241 | } else { | ||
242 | high - 10 + b'a' | ||
243 | }; | ||
244 | let lowc = if low < 10 { | ||
245 | low + b'0' | ||
246 | } else { | ||
247 | low - 10 + b'a' | ||
248 | }; | ||
241 | f.write_char(highc as char)?; | 249 | f.write_char(highc as char)?; |
242 | f.write_char(lowc as char)?; | 250 | f.write_char(lowc as char)?; |
243 | } | 251 | } |
diff --git a/rs/server/src/main.rs b/rs/server/src/main.rs index a8c6aa5..bdf38ef 100644 --- a/rs/server/src/main.rs +++ b/rs/server/src/main.rs | |||
@@ -279,7 +279,7 @@ struct BatchRequest { | |||
279 | hash_algo: HashAlgo, | 279 | hash_algo: HashAlgo, |
280 | } | 280 | } |
281 | 281 | ||
282 | #[derive(Clone)] | 282 | #[derive(Debug, Clone)] |
283 | struct GitLfsJson<T>(Json<T>); | 283 | struct GitLfsJson<T>(Json<T>); |
284 | 284 | ||
285 | const LFS_MIME: &str = "application/vnd.git-lfs+json"; | 285 | const LFS_MIME: &str = "application/vnd.git-lfs+json"; |
@@ -306,18 +306,6 @@ fn is_git_lfs_json_mimetype(mimetype: &str) -> bool { | |||
306 | let Ok(mime) = mimetype.parse::<mime::Mime>() else { | 306 | let Ok(mime) = mimetype.parse::<mime::Mime>() else { |
307 | return false; | 307 | return false; |
308 | }; | 308 | }; |
309 | println!( | ||
310 | "MIME type: {:?}; type: {}, subtype: {}, suffix: {}, charset: {}", | ||
311 | mime, | ||
312 | mime.type_(), | ||
313 | mime.subtype(), | ||
314 | mime.suffix() | ||
315 | .map(|name| name.to_string()) | ||
316 | .unwrap_or("<no suffix>".to_string()), | ||
317 | mime.get_param(mime::CHARSET) | ||
318 | .map(|name| name.to_string()) | ||
319 | .unwrap_or("<no charset>".to_string()) | ||
320 | ); | ||
321 | if mime.type_() != mime::APPLICATION | 309 | if mime.type_() != mime::APPLICATION |
322 | || mime.subtype() != "vnd.git-lfs" | 310 | || mime.subtype() != "vnd.git-lfs" |
323 | || mime.suffix() != Some(mime::JSON) | 311 | || mime.suffix() != Some(mime::JSON) |
@@ -371,7 +359,7 @@ impl<T: Serialize> IntoResponse for GitLfsJson<T> { | |||
371 | } | 359 | } |
372 | } | 360 | } |
373 | 361 | ||
374 | #[derive(Serialize)] | 362 | #[derive(Debug, Serialize)] |
375 | struct GitLfsErrorData<'a> { | 363 | struct GitLfsErrorData<'a> { |
376 | message: &'a str, | 364 | message: &'a str, |
377 | } | 365 | } |
@@ -841,7 +829,6 @@ pub struct VerifyClaimsInput<'a> { | |||
841 | pub repo_path: &'a str, | 829 | pub repo_path: &'a str, |
842 | } | 830 | } |
843 | 831 | ||
844 | // Note: expires_at is ignored. | ||
845 | fn verify_claims( | 832 | fn verify_claims( |
846 | conf: &AuthorizationConfig, | 833 | conf: &AuthorizationConfig, |
847 | claims: &VerifyClaimsInput, | 834 | claims: &VerifyClaimsInput, |
@@ -992,3 +979,31 @@ fn test_deserialize() { | |||
992 | expected | 979 | expected |
993 | ); | 980 | ); |
994 | } | 981 | } |
982 | |||
983 | #[test] | ||
984 | fn test_validate_claims() { | ||
985 | let key = "00232f7a019bd34e3921ee6c5f04caf48a4489d1be5d1999038950a7054e0bfea369ce2becc0f13fd3c69f8af2384a25b7ac2d52eb52c33722f3c00c50d4c9c2"; | ||
986 | let key: common::Key = key.parse().unwrap(); | ||
987 | |||
988 | let expires_at = Utc::now() + std::time::Duration::from_secs(5 * 60); | ||
989 | let claims = common::Claims { | ||
990 | expires_at, | ||
991 | repo_path: "lfs-test.git", | ||
992 | specific_claims: common::SpecificClaims::BatchApi(common::Operation::Download), | ||
993 | }; | ||
994 | let tag = common::generate_tag(claims, &key).unwrap(); | ||
995 | let header_value = format!("Gitolfs3-Hmac-Sha256 {tag} {}", expires_at.timestamp()); | ||
996 | |||
997 | let conf = AuthorizationConfig { | ||
998 | key, | ||
999 | trusted_forwarded_hosts: HashSet::new(), | ||
1000 | }; | ||
1001 | let claims = VerifyClaimsInput { | ||
1002 | repo_path: "lfs-test.git", | ||
1003 | specific_claims: common::SpecificClaims::BatchApi(common::Operation::Download), | ||
1004 | }; | ||
1005 | let mut headers = HeaderMap::new(); | ||
1006 | headers.insert(header::AUTHORIZATION, header_value.try_into().unwrap()); | ||
1007 | |||
1008 | assert!(verify_claims(&conf, &claims, &headers).unwrap()); | ||
1009 | } | ||