mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-11-06 08:14:07 +00:00
feat(local): check integrity for online config
This commit is contained in:
@@ -242,6 +242,10 @@ struct SSConfig {
|
||||
#[cfg(feature = "local-online-config")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
online_config: Option<SSOnlineConfig>,
|
||||
|
||||
#[cfg(feature = "local-online-config")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
version: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
@@ -425,6 +429,11 @@ pub enum ConfigType {
|
||||
|
||||
/// Config for Manager server
|
||||
Manager,
|
||||
|
||||
/// Config for online config (SIP008)
|
||||
/// https://shadowsocks.org/doc/sip008.html
|
||||
#[cfg(feature = "local-online-config")]
|
||||
OnlineConfig,
|
||||
}
|
||||
|
||||
impl ConfigType {
|
||||
@@ -442,6 +451,12 @@ impl ConfigType {
|
||||
pub fn is_manager(self) -> bool {
|
||||
self == ConfigType::Manager
|
||||
}
|
||||
|
||||
/// Chec if it is online config type (SIP008)
|
||||
#[cfg(feature = "local-online-config")]
|
||||
pub fn is_online_config(self) -> bool {
|
||||
self == ConfigType::OnlineConfig
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
@@ -1834,6 +1849,25 @@ impl Config {
|
||||
//
|
||||
// This behavior causes lots of confusion. use outbound_bind_addr instead
|
||||
}
|
||||
#[cfg(feature = "local-online-config")]
|
||||
ConfigType::OnlineConfig => {
|
||||
// SIP008. https://shadowsocks.org/doc/sip008.html
|
||||
// "version" should be set to "1"
|
||||
match config.version {
|
||||
Some(1) => {}
|
||||
Some(v) => {
|
||||
let err = Error::new(
|
||||
ErrorKind::Invalid,
|
||||
"invalid online config version",
|
||||
Some(format!("version: {v}")),
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
None => {
|
||||
warn!("OnlineConfig \"version\" is missing in the configuration, assuming it is a compatible version for this project");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Standard config
|
||||
@@ -2566,6 +2600,16 @@ impl Config {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
#[cfg(feature = "local-online-config")]
|
||||
if self.config_type.is_online_config() && self.server.is_empty() {
|
||||
let err = Error::new(
|
||||
ErrorKind::MissingField,
|
||||
"missing any valid servers in configuration",
|
||||
None,
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
if self.config_type.is_manager() && self.manager.is_none() {
|
||||
let err = Error::new(
|
||||
ErrorKind::MissingField,
|
||||
@@ -2606,6 +2650,20 @@ impl Config {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "local-online-config")]
|
||||
if self.config_type.is_online_config() {
|
||||
// Only server could bind to INADDR_ANY
|
||||
let ip = sa.ip();
|
||||
if ip.is_unspecified() {
|
||||
let err = Error::new(
|
||||
ErrorKind::Malformed,
|
||||
"`server` shouldn't be an unspecified address (INADDR_ANY)",
|
||||
None,
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
ServerAddr::DomainName(dn, port) => {
|
||||
if dn.is_empty() || *port == 0 {
|
||||
|
||||
@@ -302,7 +302,7 @@ impl Default for ServerUserManager {
|
||||
}
|
||||
|
||||
/// The source of the ServerConfig
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ServerSource {
|
||||
Default, //< Default source, created in code
|
||||
Configuration, //< Created from configuration
|
||||
|
||||
+12
-2
@@ -575,6 +575,7 @@ pub fn define_command_line_options(mut app: Command) -> Command {
|
||||
|
||||
/// Create `Runtime` and `main` entry
|
||||
pub fn create(matches: &ArgMatches) -> Result<(Runtime, impl Future<Output = ExitCode>), ExitCode> {
|
||||
#[cfg_attr(not(feature = "local-online-config"), allow(unused_mut))]
|
||||
let (mut config, runtime) = {
|
||||
let config_path_opt = matches.get_one::<PathBuf>("CONFIG").cloned().or_else(|| {
|
||||
if !matches.contains_id("SERVER_CONFIG") {
|
||||
@@ -1140,8 +1141,7 @@ async fn get_online_config_servers(
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: ConfigType::Local will force verify local_address and local_port keys. SIP008 standard doesn't include those keys.
|
||||
let online_config = match Config::load_from_str(&body, ConfigType::Server) {
|
||||
let online_config = match Config::load_from_str(&body, ConfigType::OnlineConfig) {
|
||||
Ok(c) => c,
|
||||
Err(err) => {
|
||||
error!(
|
||||
@@ -1152,6 +1152,14 @@ async fn get_online_config_servers(
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = online_config.check_integrity() {
|
||||
error!(
|
||||
"server-loader task failed to load from url: {}, error: {}",
|
||||
online_config_url, err
|
||||
);
|
||||
return Err(Box::new(err));
|
||||
}
|
||||
|
||||
Ok(online_config.server)
|
||||
}
|
||||
|
||||
@@ -1188,6 +1196,7 @@ impl ServerReloader {
|
||||
|
||||
struct ConfigDisplay<'a>(&'a ServerReloader);
|
||||
impl Display for ConfigDisplay<'_> {
|
||||
#[cfg_attr(not(feature = "local-online-config"), allow(unused_assignments, unused_variables))]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut is_first = true;
|
||||
|
||||
@@ -1266,6 +1275,7 @@ impl ServerReloader {
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
#[cfg_attr(not(feature = "local-online-config"), allow(unused_mut))]
|
||||
let mut has_things_to_do = arc_self.config_path.is_some();
|
||||
#[cfg(feature = "local-online-config")]
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user