mirror of
https://github.com/ruvnet/RuView
synced 2026-08-05 19:41:44 +00:00
fix(homecore-server): provision stable HAP identity securely
This commit is contained in:
@@ -11,6 +11,7 @@ use homecore::HomeCore;
|
|||||||
pub(crate) struct HapRuntimeConfig {
|
pub(crate) struct HapRuntimeConfig {
|
||||||
pub bind_addr: Option<SocketAddr>,
|
pub bind_addr: Option<SocketAddr>,
|
||||||
pub device_id: Option<String>,
|
pub device_id: Option<String>,
|
||||||
|
pub setup_code: Option<String>,
|
||||||
pub advertise_addr: Option<IpAddr>,
|
pub advertise_addr: Option<IpAddr>,
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
pub instance_name: String,
|
pub instance_name: String,
|
||||||
@@ -84,7 +85,24 @@ pub(crate) async fn start(hc: &HomeCore, config: HapRuntimeConfig) -> Result<Hap
|
|||||||
config.hostname.clone(),
|
config.hostname.clone(),
|
||||||
advertise_addr,
|
advertise_addr,
|
||||||
)?);
|
)?);
|
||||||
let pairings = Arc::new(PairingStore::open(&config.pairing_store)?);
|
let pairings = if config.pairing_store.exists() {
|
||||||
|
if config.setup_code.is_some() {
|
||||||
|
tracing::warn!(
|
||||||
|
"ignoring --hap-setup-code because the pairing store already exists"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PairingStore::open(&config.pairing_store)?
|
||||||
|
} else {
|
||||||
|
let setup_code = config.setup_code.as_deref().ok_or_else(|| {
|
||||||
|
anyhow::anyhow!("--hap-setup-code is required when creating a HAP pairing store")
|
||||||
|
})?;
|
||||||
|
PairingStore::create(
|
||||||
|
&config.pairing_store,
|
||||||
|
homecore_hap::SetupCode::parse(setup_code)?,
|
||||||
|
Some(device_id.to_owned()),
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
let pairings = Arc::new(pairings);
|
||||||
let record =
|
let record =
|
||||||
HapServiceRecord::bridge(config.instance_name.clone(), bind_addr.port(), device_id);
|
HapServiceRecord::bridge(config.instance_name.clone(), bind_addr.port(), device_id);
|
||||||
let bridge = HapBridge::new(record);
|
let bridge = HapBridge::new(record);
|
||||||
|
|||||||
@@ -149,6 +149,11 @@ struct Cli {
|
|||||||
#[arg(long, env = "HOMECORE_HAP_DEVICE_ID")]
|
#[arg(long, env = "HOMECORE_HAP_DEVICE_ID")]
|
||||||
hap_device_id: Option<String>,
|
hap_device_id: Option<String>,
|
||||||
|
|
||||||
|
/// HAP setup code in `XXX-XX-XXX` form. Required only when creating a
|
||||||
|
/// pairing store for the first time and never persisted in plaintext.
|
||||||
|
#[arg(long, env = "HOMECORE_HAP_SETUP_CODE", hide_env_values = true)]
|
||||||
|
hap_setup_code: Option<String>,
|
||||||
|
|
||||||
/// LAN address published in the HAP mDNS record. Required when HAP is enabled.
|
/// LAN address published in the HAP mDNS record. Required when HAP is enabled.
|
||||||
#[arg(long, env = "HOMECORE_HAP_ADVERTISE_ADDR")]
|
#[arg(long, env = "HOMECORE_HAP_ADVERTISE_ADDR")]
|
||||||
hap_advertise_addr: Option<std::net::IpAddr>,
|
hap_advertise_addr: Option<std::net::IpAddr>,
|
||||||
@@ -177,7 +182,7 @@ struct Cli {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
init_tracing();
|
init_tracing();
|
||||||
let cli = Cli::parse();
|
let mut cli = Cli::parse();
|
||||||
let has_tokens = std::env::var("HOMECORE_TOKENS")
|
let has_tokens = std::env::var("HOMECORE_TOKENS")
|
||||||
.map(|value| !value.trim().is_empty())
|
.map(|value| !value.trim().is_empty())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
@@ -325,6 +330,7 @@ async fn main() -> Result<()> {
|
|||||||
hap::HapRuntimeConfig {
|
hap::HapRuntimeConfig {
|
||||||
bind_addr: cli.hap_bind,
|
bind_addr: cli.hap_bind,
|
||||||
device_id: cli.hap_device_id.clone(),
|
device_id: cli.hap_device_id.clone(),
|
||||||
|
setup_code: cli.hap_setup_code.take(),
|
||||||
advertise_addr: cli.hap_advertise_addr,
|
advertise_addr: cli.hap_advertise_addr,
|
||||||
hostname: cli.hap_hostname.clone(),
|
hostname: cli.hap_hostname.clone(),
|
||||||
instance_name: cli.hap_instance_name.clone(),
|
instance_name: cli.hap_instance_name.clone(),
|
||||||
|
|||||||
@@ -68,11 +68,12 @@ registry currently returns a valid empty list.
|
|||||||
native plugins must be linked into the binary and registered in code.
|
native plugins must be linked into the binary and registered in code.
|
||||||
- HAP is disabled by default. Enabling it requires an explicit bind address,
|
- HAP is disabled by default. Enabling it requires an explicit bind address,
|
||||||
stable six-octet device identifier, advertised LAN address, hostname, and
|
stable six-octet device identifier, advertised LAN address, hostname, and
|
||||||
durable pairing-store path.
|
durable pairing-store path. First provisioning also requires an explicit
|
||||||
- The HAP listener fails closed for cryptographic phases that are unavailable
|
non-trivial `XXX-XX-XXX` setup code; only its SRP verifier is persisted.
|
||||||
in the selected build. Do not claim Apple Home interoperability unless the
|
- The HAP listener implements SRP-6a Pair-Setup, X25519/Ed25519 Pair-Verify,
|
||||||
Pair-Setup, Pair-Verify, and encrypted transport conformance tests for that
|
ChaCha20-Poly1305 HAP IP records, controller administration, and paired-state
|
||||||
build pass.
|
mDNS updates. Internal protocol/tamper/replay tests pass; external Apple Home
|
||||||
|
certification is not claimed.
|
||||||
- STT and TTS are provider contracts; a deployment must supply real providers.
|
- STT and TTS are provider contracts; a deployment must supply real providers.
|
||||||
The built-in disabled providers return typed errors rather than fabricated
|
The built-in disabled providers return typed errors rather than fabricated
|
||||||
speech results.
|
speech results.
|
||||||
|
|||||||
Reference in New Issue
Block a user