prevent unauthorized access to administrative db0 when connection to redis-cli
This commit is contained in:
@@ -21,6 +21,8 @@ use ureq::{Agent, AgentBuilder};
|
||||
use std::time::Duration;
|
||||
use std::io::Read;
|
||||
|
||||
const NO_DB_SELECTED: u64 = u64::MAX;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Server {
|
||||
pub db_cache: std::sync::Arc<std::sync::RwLock<HashMap<u64, Arc<dyn StorageBackend>>>>,
|
||||
@@ -65,7 +67,7 @@ impl Server {
|
||||
db_cache: Arc::new(std::sync::RwLock::new(HashMap::new())),
|
||||
option,
|
||||
client_name: None,
|
||||
selected_db: 0,
|
||||
selected_db: NO_DB_SELECTED,
|
||||
queued_cmd: None,
|
||||
current_permissions: None,
|
||||
|
||||
@@ -103,6 +105,17 @@ impl Server {
|
||||
}
|
||||
|
||||
pub fn current_storage(&self) -> Result<Arc<dyn StorageBackend>, DBError> {
|
||||
// Require explicit SELECT before any storage access
|
||||
if self.selected_db == NO_DB_SELECTED {
|
||||
return Err(DBError("No database selected. Use SELECT <id> [KEY <key>] first".to_string()));
|
||||
}
|
||||
// Admin DB 0 access must be authenticated with SELECT 0 KEY <admin_secret>
|
||||
if self.selected_db == 0 {
|
||||
if !matches!(self.current_permissions, Some(crate::rpc::Permissions::ReadWrite)) {
|
||||
return Err(DBError("Admin DB 0 requires SELECT 0 KEY <admin_secret>".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut cache = self.db_cache.write().unwrap();
|
||||
|
||||
if let Some(storage) = cache.get(&self.selected_db) {
|
||||
@@ -328,6 +341,10 @@ impl Server {
|
||||
|
||||
/// Check if current permissions allow read operations
|
||||
pub fn has_read_permission(&self) -> bool {
|
||||
// No DB selected -> no permissions
|
||||
if self.selected_db == NO_DB_SELECTED {
|
||||
return false;
|
||||
}
|
||||
// If an explicit permission is set for this connection, honor it.
|
||||
if let Some(perms) = self.current_permissions.as_ref() {
|
||||
return matches!(*perms, crate::rpc::Permissions::Read | crate::rpc::Permissions::ReadWrite);
|
||||
@@ -347,6 +364,10 @@ impl Server {
|
||||
|
||||
/// Check if current permissions allow write operations
|
||||
pub fn has_write_permission(&self) -> bool {
|
||||
// No DB selected -> no permissions
|
||||
if self.selected_db == NO_DB_SELECTED {
|
||||
return false;
|
||||
}
|
||||
// If an explicit permission is set for this connection, honor it.
|
||||
if let Some(perms) = self.current_permissions.as_ref() {
|
||||
return matches!(*perms, crate::rpc::Permissions::ReadWrite);
|
||||
|
||||
Reference in New Issue
Block a user