rvoip_rtp_core/api/server/security/
mod.rs

1//! Server security API
2//!
3//! This module provides security-related interfaces for the server-side media transport.
4
5use std::net::SocketAddr;
6use std::sync::Arc;
7use std::any::Any;
8use async_trait::async_trait;
9use tokio::net::UdpSocket;
10use tokio::sync::Mutex;
11
12use crate::api::common::error::SecurityError;
13use crate::api::common::config::{SecurityInfo, SecurityMode, SrtpProfile};
14
15// Import necessary modules as public
16pub mod default;
17pub mod core;
18pub mod client;
19pub mod dtls;
20pub mod srtp;
21pub mod util;
22
23// Re-export DefaultServerSecurityContext
24pub use default::DefaultServerSecurityContext;
25pub use client::context::DefaultClientSecurityContext;
26
27// Define our own types for API compatibility
28/// Socket handle for network operations
29#[derive(Clone)]
30pub struct SocketHandle {
31    /// The underlying UDP socket
32    pub socket: Arc<UdpSocket>,
33    /// The remote address
34    pub remote_addr: Option<SocketAddr>,
35}
36
37/// DTLS connection configuration
38#[derive(Clone)]
39pub struct ConnectionConfig {
40    /// Is this a client or server connection
41    pub role: ConnectionRole,
42    /// SRTP profiles to negotiate
43    pub srtp_profiles: Vec<SrtpProfile>,
44    /// Fingerprint algorithm to use
45    pub fingerprint_algorithm: String,
46    /// Certificate path if using custom certificate
47    pub certificate_path: Option<String>,
48    /// Private key path if using custom certificate
49    pub private_key_path: Option<String>,
50}
51
52impl Default for ConnectionConfig {
53    fn default() -> Self {
54        Self {
55            role: ConnectionRole::Server,
56            srtp_profiles: vec![SrtpProfile::AesCm128HmacSha1_80, SrtpProfile::AesGcm128],
57            fingerprint_algorithm: "sha-256".to_string(),
58            certificate_path: None,
59            private_key_path: None,
60        }
61    }
62}
63
64/// DTLS connection role
65#[derive(Clone)]
66pub enum ConnectionRole {
67    /// Client role (initiates handshake)
68    Client,
69    /// Server role (responds to handshake)
70    Server,
71}
72
73/// Server security configuration
74#[derive(Debug, Clone)]
75pub struct ServerSecurityConfig {
76    /// Security mode to use
77    pub security_mode: SecurityMode,
78    /// DTLS fingerprint algorithm
79    pub fingerprint_algorithm: String,
80    /// Path to certificate file (PEM format)
81    pub certificate_path: Option<String>,
82    /// Path to private key file (PEM format)
83    pub private_key_path: Option<String>,
84    /// SRTP profiles supported (in order of preference)
85    pub srtp_profiles: Vec<SrtpProfile>,
86    /// Whether to require client certificate
87    pub require_client_certificate: bool,
88    /// Pre-shared SRTP key (for SRTP mode)
89    pub srtp_key: Option<Vec<u8>>,
90}
91
92impl Default for ServerSecurityConfig {
93    fn default() -> Self {
94        Self {
95            security_mode: SecurityMode::DtlsSrtp,
96            fingerprint_algorithm: "sha-256".to_string(),
97            certificate_path: None,
98            private_key_path: None,
99            srtp_profiles: vec![
100                SrtpProfile::AesCm128HmacSha1_80,
101                SrtpProfile::AesGcm128,
102            ],
103            require_client_certificate: false,
104            srtp_key: None,
105        }
106    }
107}
108
109/// Client security context for a client connected to the server
110///
111/// This trait defines the interface for handling security with a specific client.
112#[async_trait]
113pub trait ClientSecurityContext: Send + Sync {
114    /// Set the socket for the client security context
115    async fn set_socket(&self, socket: SocketHandle) -> Result<(), SecurityError>;
116    
117    /// Get the client's fingerprint
118    async fn get_remote_fingerprint(&self) -> Result<Option<String>, SecurityError>;
119    
120    /// Get the local fingerprint (server's fingerprint)
121    async fn get_fingerprint(&self) -> Result<String, SecurityError>;
122    
123    /// Get the local fingerprint algorithm (server's algorithm)
124    async fn get_fingerprint_algorithm(&self) -> Result<String, SecurityError>;
125    
126    /// Close the client security context
127    async fn close(&self) -> Result<(), SecurityError>;
128    
129    /// Is the connection secure?
130    fn is_secure(&self) -> bool;
131    
132    /// Get security information about this client
133    fn get_security_info(&self) -> SecurityInfo;
134    
135    /// Wait for the DTLS handshake to complete
136    async fn wait_for_handshake(&self) -> Result<(), SecurityError>;
137    
138    /// Verify if the handshake is complete
139    async fn is_handshake_complete(&self) -> Result<bool, SecurityError>;
140    
141    /// Process a DTLS packet received from the client
142    async fn process_dtls_packet(&self, data: &[u8]) -> Result<(), SecurityError>;
143    
144    /// Start a handshake with the remote
145    async fn start_handshake_with_remote(&self, remote_addr: SocketAddr) -> Result<(), SecurityError>;
146    
147    /// Allow downcasting for internal implementation details
148    fn as_any(&self) -> &dyn Any;
149}
150
151/// Server security context
152///
153/// This trait defines the interface for server-side security operations.
154#[async_trait]
155pub trait ServerSecurityContext: Send + Sync {
156    /// Initialize the server security context
157    async fn initialize(&self) -> Result<(), SecurityError>;
158    
159    /// Set the main socket for the server
160    async fn set_socket(&self, socket: SocketHandle) -> Result<(), SecurityError>;
161    
162    /// Get the server's DTLS fingerprint
163    async fn get_fingerprint(&self) -> Result<String, SecurityError>;
164    
165    /// Get the server's fingerprint algorithm
166    async fn get_fingerprint_algorithm(&self) -> Result<String, SecurityError>;
167    
168    /// Start listening for incoming DTLS connections
169    async fn start_listening(&self) -> Result<(), SecurityError>;
170    
171    /// Stop listening for incoming DTLS connections
172    async fn stop_listening(&self) -> Result<(), SecurityError>;
173    
174    /// Start automatic packet handler to process incoming DTLS packets
175    /// This creates a background task that receives packets from the socket
176    /// and automatically passes them to process_client_packet
177    async fn start_packet_handler(&self) -> Result<(), SecurityError>;
178    
179    /// Capture the first packet from a client for proper handshake sequence
180    async fn capture_initial_packet(&self) -> Result<Option<(Vec<u8>, SocketAddr)>, SecurityError>;
181    
182    /// Create a security context for a new client
183    async fn create_client_context(&self, addr: SocketAddr) -> Result<Arc<dyn ClientSecurityContext + Send + Sync>, SecurityError>;
184    
185    /// Get all client security contexts
186    async fn get_client_contexts(&self) -> Vec<Arc<dyn ClientSecurityContext + Send + Sync>>;
187    
188    /// Remove a client security context
189    async fn remove_client(&self, addr: SocketAddr) -> Result<(), SecurityError>;
190    
191    /// Register a callback for clients that complete security setup
192    async fn on_client_secure(&self, callback: Box<dyn Fn(Arc<dyn ClientSecurityContext + Send + Sync>) + Send + Sync>) -> Result<(), SecurityError>;
193    
194    /// Get the list of supported SRTP profiles
195    async fn get_supported_srtp_profiles(&self) -> Vec<SrtpProfile>;
196    
197    /// Is the server using secure transport?
198    fn is_secure(&self) -> bool;
199    
200    /// Get security information about the server
201    fn get_security_info(&self) -> SecurityInfo;
202    
203    /// Process a packet from a specific client for DTLS handshake
204    async fn process_client_packet(&self, addr: SocketAddr, data: &[u8]) -> Result<(), SecurityError>;
205    
206    /// Check if the server is fully initialized and ready to process handshake messages
207    /// This verifies that all prerequisites (socket, etc.) are set
208    async fn is_ready(&self) -> Result<bool, SecurityError>;
209    
210    /// Get the security configuration
211    fn get_config(&self) -> &ServerSecurityConfig;
212}
213
214/// Create a new server security context
215pub async fn new(config: ServerSecurityConfig) -> Result<Arc<dyn ServerSecurityContext + Send + Sync>, SecurityError> {
216    match config.security_mode {
217        SecurityMode::Srtp => {
218            // Use SRTP-only context for pre-shared keys (no DTLS handshake)
219            let srtp_ctx = srtp::SrtpServerSecurityContext::new(config).await?;
220            Ok(srtp_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
221        },
222        SecurityMode::DtlsSrtp => {
223            // Use DTLS-SRTP context for handshake-based keys
224            let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
225            Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
226        },
227        SecurityMode::SdesSrtp |
228        SecurityMode::MikeySrtp |
229        SecurityMode::ZrtpSrtp => {
230            // For now, treat these as DTLS-based (they would need specific implementations)
231            let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
232            Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
233        },
234        SecurityMode::None => {
235            // For None, we could return a no-op security context, but for now use DTLS as fallback
236            let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
237            Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
238        }
239    }
240}