Fix code quality: trailing whitespace, unused imports, clippy warnings
- Fix trailing whitespace in kex.rs and s3.rs - Add missing KexProposal import in kex_complete.rs - Auto-fix clippy warnings across all crates - All 153 tests pass
This commit is contained in:
@@ -12,20 +12,22 @@ fn get_test_provider() -> Arc<dyn DataProvider> {
|
||||
#[test]
|
||||
fn test_password_authentication_brute_force_prevention() {
|
||||
let provider = get_test_provider();
|
||||
|
||||
|
||||
assert!(provider.check_password("demo", "demo123").unwrap());
|
||||
assert!(!provider.check_password("demo", "wrongpassword").unwrap());
|
||||
assert!(!provider.check_password("demo", "").unwrap());
|
||||
assert!(!provider.check_password("__nonexistent__", "anypassword").unwrap());
|
||||
assert!(!provider
|
||||
.check_password("__nonexistent__", "anypassword")
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_publickey_authentication_security() {
|
||||
let provider = get_test_provider();
|
||||
|
||||
|
||||
let keys = provider.get_public_keys("demo").unwrap();
|
||||
assert!(keys.is_empty() || keys.len() >= 0);
|
||||
|
||||
|
||||
let keys = provider.get_public_keys("__nonexistent__").unwrap();
|
||||
assert!(keys.is_empty());
|
||||
}
|
||||
@@ -33,10 +35,10 @@ fn test_publickey_authentication_security() {
|
||||
#[test]
|
||||
fn test_user_status_check() {
|
||||
let provider = get_test_provider();
|
||||
|
||||
|
||||
let user = provider.get_user("demo").unwrap();
|
||||
assert!(user.is_some());
|
||||
|
||||
|
||||
let user = provider.get_user("demo").unwrap();
|
||||
if let Some(u) = user {
|
||||
assert_eq!(u.status, 1);
|
||||
@@ -46,16 +48,16 @@ fn test_user_status_check() {
|
||||
#[test]
|
||||
fn test_home_dir_security() {
|
||||
let provider = get_test_provider();
|
||||
|
||||
|
||||
let home = provider.get_home_dir("demo").unwrap();
|
||||
assert!(home.is_some());
|
||||
|
||||
|
||||
let home = provider.get_home_dir("__nonexistent__").unwrap();
|
||||
assert!(home.is_none());
|
||||
|
||||
|
||||
if let Some(home_path) = provider.get_home_dir("demo").unwrap() {
|
||||
assert!(!home_path.contains(".."));
|
||||
assert!(!home_path.starts_with("/etc"));
|
||||
assert!(!home_path.starts_with("/root"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ fn test_channel_window_size_limits() {
|
||||
#[test]
|
||||
fn test_channel_request_validation() {
|
||||
let valid_requests = ["exec", "shell", "subsystem", "env"];
|
||||
|
||||
|
||||
for request in valid_requests {
|
||||
assert!(!request.is_empty());
|
||||
}
|
||||
@@ -30,6 +30,6 @@ fn test_channel_data_integrity() {
|
||||
// Data should not exceed window size
|
||||
let window_size = 32768u32;
|
||||
let max_data = window_size;
|
||||
|
||||
|
||||
assert!(max_data <= window_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::ssh_server::cipher::EncryptionContext;
|
||||
use crate::ssh_server::crypto::{SessionKeys, Curve25519Kex, Ed25519HostKey};
|
||||
use crate::ssh_server::crypto::{Curve25519Kex, Ed25519HostKey, SessionKeys};
|
||||
|
||||
#[test]
|
||||
fn test_aes_ctr_encryption_decryption_consistency() {
|
||||
let key = vec![0u8; 16];
|
||||
let iv = vec![0u8; 16];
|
||||
|
||||
|
||||
let mut ctx = EncryptionContext::from_session_keys(&SessionKeys {
|
||||
session_id: vec![0u8; 32],
|
||||
encryption_key_ctos: key.clone(),
|
||||
@@ -15,10 +15,10 @@ fn test_aes_ctr_encryption_decryption_consistency() {
|
||||
iv_ctos: iv.clone(),
|
||||
iv_stoc: iv.clone(),
|
||||
});
|
||||
|
||||
|
||||
let plaintext = b"Test message for encryption";
|
||||
let ciphertext = ctx.encrypt_packet(plaintext, &key, &iv).unwrap();
|
||||
|
||||
|
||||
let decrypted = ctx.decrypt_packet(&ciphertext, &key, &iv).unwrap();
|
||||
assert_eq!(plaintext.to_vec(), decrypted);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ fn test_aes_ctr_encryption_decryption_consistency() {
|
||||
fn test_hmac_sha256_authentication() {
|
||||
let key = vec![0u8; 32];
|
||||
let data = b"Test data for HMAC";
|
||||
|
||||
|
||||
let ctx = EncryptionContext::from_session_keys(&SessionKeys {
|
||||
session_id: vec![0u8; 32],
|
||||
encryption_key_ctos: vec![0u8; 16],
|
||||
@@ -37,12 +37,12 @@ fn test_hmac_sha256_authentication() {
|
||||
iv_ctos: vec![0u8; 16],
|
||||
iv_stoc: vec![0u8; 16],
|
||||
});
|
||||
|
||||
|
||||
let mac = ctx.compute_mac(1, data, &key).unwrap();
|
||||
assert_eq!(mac.len(), 32);
|
||||
|
||||
|
||||
assert!(ctx.verify_mac(1, data, &mac, &key).unwrap());
|
||||
|
||||
|
||||
let wrong_mac = vec![0u8; 32];
|
||||
assert!(!ctx.verify_mac(1, data, &wrong_mac, &key).unwrap());
|
||||
}
|
||||
@@ -52,19 +52,19 @@ fn test_curve25519_key_exchange_security() {
|
||||
// Create client and server instances
|
||||
let mut client_kex = Curve25519Kex::new();
|
||||
let mut server_kex = Curve25519Kex::new();
|
||||
|
||||
|
||||
// Get public keys first (before computing shared secrets)
|
||||
let client_pub = client_kex.public_key().to_vec();
|
||||
let server_pub = server_kex.public_key().to_vec();
|
||||
|
||||
|
||||
assert_eq!(client_pub.len(), 32);
|
||||
assert_eq!(server_pub.len(), 32);
|
||||
|
||||
|
||||
// Compute shared secrets using the SAME instances
|
||||
// (this consumes the secret, so can only be done once)
|
||||
let client_secret = client_kex.compute_shared_secret(&server_pub).unwrap();
|
||||
let server_secret = server_kex.compute_shared_secret(&client_pub).unwrap();
|
||||
|
||||
|
||||
// Shared secrets should match (Diffie-Hellman property)
|
||||
assert_eq!(client_secret, server_secret);
|
||||
assert_eq!(client_secret.len(), 32);
|
||||
@@ -73,12 +73,12 @@ fn test_curve25519_key_exchange_security() {
|
||||
#[test]
|
||||
fn test_ed25519_signature_verification() {
|
||||
let host_key = Ed25519HostKey::load_or_generate("test_security_key").unwrap();
|
||||
|
||||
|
||||
let message = b"Test message for signature";
|
||||
let signature = host_key.sign(message).unwrap();
|
||||
|
||||
|
||||
assert_eq!(signature.len(), 64);
|
||||
|
||||
|
||||
// Ed25519HostKey has sign() but verify might need external library
|
||||
// For security test, we verify signature length and structure
|
||||
assert!(!signature.is_empty());
|
||||
@@ -89,9 +89,9 @@ fn test_encryption_key_derivation_uniqueness() {
|
||||
let key1 = vec![1u8; 16];
|
||||
let key2 = vec![2u8; 16];
|
||||
let iv = vec![0u8; 16];
|
||||
|
||||
|
||||
let plaintext = b"Same plaintext";
|
||||
|
||||
|
||||
let mut ctx1 = EncryptionContext::from_session_keys(&SessionKeys {
|
||||
session_id: vec![0u8; 32],
|
||||
encryption_key_ctos: key1.clone(),
|
||||
@@ -101,7 +101,7 @@ fn test_encryption_key_derivation_uniqueness() {
|
||||
iv_ctos: iv.clone(),
|
||||
iv_stoc: iv.clone(),
|
||||
});
|
||||
|
||||
|
||||
let mut ctx2 = EncryptionContext::from_session_keys(&SessionKeys {
|
||||
session_id: vec![0u8; 32],
|
||||
encryption_key_ctos: key2.clone(),
|
||||
@@ -111,9 +111,9 @@ fn test_encryption_key_derivation_uniqueness() {
|
||||
iv_ctos: iv.clone(),
|
||||
iv_stoc: iv.clone(),
|
||||
});
|
||||
|
||||
|
||||
let ciphertext1 = ctx1.encrypt_packet(plaintext, &key1, &iv).unwrap();
|
||||
let ciphertext2 = ctx2.encrypt_packet(plaintext, &key2, &iv).unwrap();
|
||||
|
||||
|
||||
assert_ne!(ciphertext1, ciphertext2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,17 @@ use std::path::PathBuf;
|
||||
#[test]
|
||||
fn test_path_traversal_prevention() {
|
||||
let root = PathBuf::from("/tmp/test_root");
|
||||
|
||||
|
||||
// Test 1: Normal path should be within root
|
||||
let safe_path = PathBuf::from("safe/file.txt");
|
||||
let full_path = root.join(&safe_path);
|
||||
assert!(full_path.starts_with(&root));
|
||||
|
||||
|
||||
// Test 2: Path traversal attempt should still resolve within root
|
||||
// (after normalization, ../../etc/passwd from /tmp/test_root becomes /tmp/etc/passwd or /etc/passwd)
|
||||
let evil_path = PathBuf::from("../../etc/passwd");
|
||||
let full_path = root.join(&evil_path);
|
||||
|
||||
|
||||
// The key security check: the resolved path should NOT be /etc/passwd
|
||||
// If Path::join normalizes it to /etc/passwd, that's a path traversal vulnerability
|
||||
// We check that the joined path either:
|
||||
@@ -34,7 +34,7 @@ fn test_path_traversal_prevention() {
|
||||
#[test]
|
||||
fn test_absolute_path_prevention() {
|
||||
let root = PathBuf::from("/tmp/test_root");
|
||||
|
||||
|
||||
let abs_path = PathBuf::from("/etc/passwd");
|
||||
assert!(!abs_path.starts_with(&root));
|
||||
}
|
||||
@@ -42,10 +42,10 @@ fn test_absolute_path_prevention() {
|
||||
#[test]
|
||||
fn test_directory_escape_prevention() {
|
||||
let root = PathBuf::from("/tmp/test_root");
|
||||
|
||||
|
||||
let parent_path = PathBuf::from("subdir/../..");
|
||||
let full_path = root.join(&parent_path);
|
||||
|
||||
|
||||
// Path should not escape root
|
||||
if full_path.canonicalize().is_ok() {
|
||||
let canonical = full_path.canonicalize().unwrap();
|
||||
@@ -56,11 +56,11 @@ fn test_directory_escape_prevention() {
|
||||
#[test]
|
||||
fn test_file_write_boundary_check() {
|
||||
let root = PathBuf::from("/tmp/test_root");
|
||||
|
||||
|
||||
let safe_file = PathBuf::from("safe.txt");
|
||||
let full_path = root.join(&safe_file);
|
||||
assert!(full_path.starts_with(&root));
|
||||
|
||||
|
||||
let outside_file = PathBuf::from("/tmp/outside.txt");
|
||||
assert!(!outside_file.starts_with(&root));
|
||||
}
|
||||
@@ -68,8 +68,8 @@ fn test_file_write_boundary_check() {
|
||||
#[test]
|
||||
fn test_hidden_file_access() {
|
||||
let root = PathBuf::from("/tmp/test_root");
|
||||
|
||||
|
||||
let hidden_path = PathBuf::from(".hidden");
|
||||
let full_path = root.join(&hidden_path);
|
||||
assert!(full_path.starts_with(&root));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
mod auth_security;
|
||||
mod channel_security;
|
||||
mod crypto_security;
|
||||
mod file_access_security;
|
||||
mod channel_security;
|
||||
|
||||
pub use auth_security::*;
|
||||
pub use channel_security::*;
|
||||
pub use crypto_security::*;
|
||||
pub use file_access_security::*;
|
||||
pub use channel_security::*;
|
||||
Reference in New Issue
Block a user