Skip to content

Commit

Permalink
fix: auto-remove failed SmartStart nodes when bootstrapping times out (
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored Oct 31, 2023
1 parent 27f5457 commit 6c33fdb
Showing 1 changed file with 33 additions and 13 deletions.
46 changes: 33 additions & 13 deletions packages/zwave-js/src/lib/controller/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,17 @@ supported CCs: ${
return SecurityBootstrapFailure.UserCanceled;
};

const abortTimeout = async () => {
this.driver.controllerLog.logNode(node.id, {
message:
`Security S2 bootstrapping failed: a secure inclusion timer has elapsed`,
level: "warn",
});

await abort();
return SecurityBootstrapFailure.Timeout;
};

// Ask the node for its desired security classes and key exchange params
const kexParams = await api
.withOptions({ reportTimeoutMs: inclusionTimeouts.TA1 })
Expand Down Expand Up @@ -2876,7 +2887,8 @@ supported CCs: ${
cc instanceof Security2CCPublicKeyReport
|| cc instanceof Security2CCKEXFail,
inclusionTimeouts.TA2,
);
).catch(() => "timeout" as const);
if (pubKeyResponse === "timeout") return abortTimeout();
if (
pubKeyResponse instanceof Security2CCKEXFail
|| pubKeyResponse.includingNode
Expand Down Expand Up @@ -2990,25 +3002,26 @@ supported CCs: ${
return abortUser();
}

const keySetEcho = await Promise.race([
const kexSetEcho = await Promise.race([
this.driver.waitForCommand<
Security2CCKEXSet | Security2CCKEXFail
>(
(cc) =>
cc instanceof Security2CCKEXSet
|| cc instanceof Security2CCKEXFail,
tai2RemainingMs,
),
).catch(() => "timeout" as const),
this.cancelBootstrapS2Promise,
]);
if (typeof keySetEcho === "number") {
if (kexSetEcho === "timeout") return abortTimeout();
if (typeof kexSetEcho === "number") {
// The bootstrapping process was canceled - this is most likely because the PIN was incorrect
// and the node's commands cannot be decoded
await abort(keySetEcho);
await abort(kexSetEcho);
return SecurityBootstrapFailure.S2IncorrectPIN;
}
// Validate that the received command contains the correct list of keys
if (keySetEcho instanceof Security2CCKEXFail) {
if (kexSetEcho instanceof Security2CCKEXFail) {
this.driver.controllerLog.logNode(node.id, {
message:
`The joining node canceled the Security S2 bootstrapping.`,
Expand All @@ -3017,7 +3030,7 @@ supported CCs: ${
});
await abort();
return SecurityBootstrapFailure.NodeCanceled;
} else if (!keySetEcho.echo) {
} else if (!kexSetEcho.echo) {
this.driver.controllerLog.logNode(node.id, {
message:
`Security S2 bootstrapping failed: KEXSet received without echo flag`,
Expand All @@ -3027,7 +3040,7 @@ supported CCs: ${
await abort(KEXFailType.WrongSecurityLevel);
return SecurityBootstrapFailure.NodeCanceled;
} else if (
!keySetEcho.isEncapsulatedWith(
!kexSetEcho.isEncapsulatedWith(
CommandClasses["Security 2"],
Security2Command.MessageEncapsulation,
)
Expand All @@ -3041,8 +3054,8 @@ supported CCs: ${
await abort(KEXFailType.WrongSecurityLevel);
return SecurityBootstrapFailure.S2WrongSecurityLevel;
} else if (
keySetEcho.grantedKeys.length !== grantedKeys.length
|| !keySetEcho.grantedKeys.every((k) => grantedKeys.includes(k))
kexSetEcho.grantedKeys.length !== grantedKeys.length
|| !kexSetEcho.grantedKeys.every((k) => grantedKeys.includes(k))
) {
this.driver.controllerLog.logNode(node.id, {
message:
Expand Down Expand Up @@ -3070,7 +3083,8 @@ supported CCs: ${
cc instanceof Security2CCNetworkKeyGet
|| cc instanceof Security2CCKEXFail,
inclusionTimeouts.TA3,
);
).catch(() => "timeout" as const);
if (keyRequest === "timeout") return abortTimeout();
if (keyRequest instanceof Security2CCKEXFail) {
this.driver.controllerLog.logNode(node.id, {
message:
Expand Down Expand Up @@ -3127,7 +3141,8 @@ supported CCs: ${
cc instanceof Security2CCNetworkKeyVerify
|| cc instanceof Security2CCKEXFail,
inclusionTimeouts.TA4,
);
).catch(() => "timeout" as const);
if (verify === "timeout") return abortTimeout();
if (verify instanceof Security2CCKEXFail) {
this.driver.controllerLog.logNode(node.id, {
message:
Expand Down Expand Up @@ -3169,7 +3184,8 @@ supported CCs: ${
>(
(cc) => cc instanceof Security2CCTransferEnd,
inclusionTimeouts.TA5,
);
).catch(() => "timeout" as const);
if (transferEnd === "timeout") return abortTimeout();
if (!transferEnd.keyRequestComplete) {
// S2 bootstrapping failed
this.driver.controllerLog.logNode(node.id, {
Expand Down Expand Up @@ -3209,10 +3225,12 @@ supported CCs: ${
} catch (e) {
let errorMessage =
`Security S2 bootstrapping failed, the node was not granted any S2 security class`;
let result = SecurityBootstrapFailure.Unknown;
if (!isZWaveError(e)) {
errorMessage += `: ${e as any}`;
} else if (e.code === ZWaveErrorCodes.Controller_MessageExpired) {
errorMessage += ": a secure inclusion timer has elapsed.";
result = SecurityBootstrapFailure.Timeout;
} else if (
e.code !== ZWaveErrorCodes.Controller_MessageDropped
&& e.code !== ZWaveErrorCodes.Controller_NodeTimeout
Expand All @@ -3223,6 +3241,8 @@ supported CCs: ${
// Remember that the node was NOT granted any S2 security classes
unGrantSecurityClasses();
node.removeCC(CommandClasses["Security 2"]);

return result;
} finally {
// Whatever happens, no further communication needs the temporary key
deleteTempKey();
Expand Down

0 comments on commit 6c33fdb

Please sign in to comment.