ZWave: SECURITY inclusion experiments (Forum #37121)
git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@8636 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -185,7 +185,7 @@ ZWDongle_Initialize($)
|
||||
$hash->{AttrFn} = "ZWDongle_Attr";
|
||||
$hash->{UndefFn} = "ZWDongle_Undef";
|
||||
$hash->{AttrList}=
|
||||
"do_not_notify:1,0 dummy:1,0 model:ZWDongle disable:0,1 homeId";
|
||||
"do_not_notify:1,0 dummy:1,0 model:ZWDongle disable:0,1 homeId networkKey";
|
||||
}
|
||||
|
||||
#####################################
|
||||
@@ -650,21 +650,6 @@ ZWDongle_Parse($$$)
|
||||
|
||||
my %addvals = (RAWMSG => $rmsg);
|
||||
|
||||
if($rmsg =~ m/^01(..)(..*)/) { # 01==ANSWER
|
||||
my ($cmd, $arg) = ($1, $2);
|
||||
$cmd = $zw_func_id{$cmd} if($zw_func_id{$cmd});
|
||||
if($cmd eq "ZW_SEND_DATA") {
|
||||
Log3 $hash, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1);
|
||||
return "";
|
||||
}
|
||||
if($cmd eq "SERIAL_API_SET_TIMEOUTS" && $arg =~ m/(..)(..)/) {
|
||||
Log3 $hash, 2, "SERIAL_API_SET_TIMEOUTS: ACK:$1 BYTES:$2";
|
||||
return "";
|
||||
}
|
||||
Log3 $hash, 4, "$name unhandled ANSWER: $cmd $arg";
|
||||
return "";
|
||||
}
|
||||
|
||||
Dispatch($hash, $rmsg, \%addvals);
|
||||
}
|
||||
|
||||
@@ -692,6 +677,11 @@ ZWDongle_Attr($$$$)
|
||||
} elsif($attr eq "homeId") {
|
||||
$hash->{homeId} = $value;
|
||||
|
||||
} elsif($attr eq "networkKey") {
|
||||
if(!$value || $value !~ m/^[0-9A-F]{32}$/i) {
|
||||
return "attr $name networkKey: not a hex string with a length of 32";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return undef;
|
||||
|
||||
@@ -282,7 +282,7 @@ my %zwave_class = (
|
||||
associationDel => "04%02x%02x*" },
|
||||
get => { association => "02%02x", },
|
||||
parse => { "..8503(..)(..)..(.*)" => '"assocGroup_$1:Max $2 Nodes $3"'},
|
||||
init => { ORDER=> 1, CMD=> '"set $NAME associationAdd 1 $CTRLID"' } },
|
||||
init => { ORDER=>10, CMD=> '"set $NAME associationAdd 1 $CTRLID"' } },
|
||||
VERSION => { id => '86',
|
||||
get => { version => "11",
|
||||
versionClass => "13%02x" },
|
||||
@@ -322,7 +322,14 @@ my %zwave_class = (
|
||||
AV_CONTENT_DIRECTORY_MD => { id => '95' },
|
||||
AV_RENDERER_STATUS => { id => '96' },
|
||||
AV_CONTENT_SEARCH_MD => { id => '97' },
|
||||
SECURITY => { id => '98' },
|
||||
SECURITY => { id => '98',
|
||||
set => { "secKey" => '(undef, "06%s")',
|
||||
"secScheme" => "0400",
|
||||
"secNonce" => "40" },
|
||||
get => { "secSupported" => "02" },
|
||||
parse => { "..9803(.*)" => '"secSupported:$1"',
|
||||
"..9805(.*)" => 'ZWave_securityInit($hash, $1)',
|
||||
"..9880(.*)" => 'ZWave_securityInit($hash, $1)' } },
|
||||
AV_TAGGING_MD => { id => '99' },
|
||||
IP_CONFIGURATION => { id => '9a' },
|
||||
ASSOCIATION_COMMAND_CONFIGURATION
|
||||
@@ -418,7 +425,6 @@ ZWave_Define($$)
|
||||
if(@a) { # Autocreate: set the classes, execute the init calls
|
||||
$hash->{lastMsgTimestamp} = time(); # device is awake.
|
||||
ZWave_SetClasses($homeId, $id, undef, $a[0]);
|
||||
ZWave_execInits($hash, 0);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -598,7 +604,7 @@ ZWave_Cmd($$@)
|
||||
$baseHash->{WakeUp} = \@arr;
|
||||
}
|
||||
my $awake = ($baseHash->{lastMsgTimestamp} &&
|
||||
time() - $baseHash->{lastMsgTimestamp} < 2);
|
||||
time() - $baseHash->{lastMsgTimestamp} < 3);
|
||||
|
||||
if(!$awake) {
|
||||
push @{$baseHash->{WakeUp}}, $data.$id;
|
||||
@@ -1424,6 +1430,40 @@ ZWave_sensorbinaryV2Parse($$)
|
||||
":".$value;
|
||||
}
|
||||
|
||||
sub
|
||||
ZWave_securityInit(@)
|
||||
{
|
||||
my ($hash, $param) = @_;
|
||||
my $iodev = $hash->{IODev};
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
$hash->{secStatus} = 0 if(!$hash->{secStatus});
|
||||
my $status = ++$hash->{secStatus};
|
||||
|
||||
Log3 $iodev, 4, "$hash->{NAME}: securityInit status $status";
|
||||
if($status == 1) {
|
||||
ZWave_Set($hash, $name, "secScheme");
|
||||
return ""; # not evaluated
|
||||
|
||||
} elsif($status == 2) {
|
||||
Log3 $iodev, 4, "secScheme report: $param";
|
||||
my $key = AttrVal($iodev->{NAME}, "networkKey", "");
|
||||
ZWave_Set($hash, $name, ("secKey", $key));
|
||||
return undef; # No Event/Reading
|
||||
|
||||
} elsif($status == 3) {
|
||||
ZWave_Set($hash, $name, "secNonce");
|
||||
return undef; # No Event/Reading
|
||||
|
||||
} else {
|
||||
Log3 $iodev, 4, "secNonce report: $param";
|
||||
delete $iodev->{secInitName};
|
||||
delete $hash->{secStatus};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
ZWave_getHash($$$)
|
||||
{
|
||||
@@ -1474,6 +1514,26 @@ ZWave_Parse($$@)
|
||||
$iodev->{errReported} = 1;
|
||||
return "";
|
||||
}
|
||||
|
||||
if($msg =~ m/^01(..)(..*)/) { # 01==ANSWER
|
||||
my ($cmd, $arg) = ($1, $2);
|
||||
$cmd = $zw_func_id{$cmd} if($zw_func_id{$cmd});
|
||||
if($cmd eq "ZW_SEND_DATA") {
|
||||
Log3 $ioName, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1);
|
||||
my $si = $iodev->{secInitName};
|
||||
ZWave_securityInit($defs{$si}) # No extra response for set networkKey
|
||||
if($si && $defs{$si} && $defs{$si}{secStatus} &&
|
||||
$defs{$si}{secStatus} == 2);
|
||||
return "";
|
||||
}
|
||||
if($cmd eq "SERIAL_API_SET_TIMEOUTS" && $arg =~ m/(..)(..)/) {
|
||||
Log3 $ioName, 2, "SERIAL_API_SET_TIMEOUTS: ACK:$1 BYTES:$2";
|
||||
return "";
|
||||
}
|
||||
Log3 $ioName, 4, "$ioName unhandled ANSWER: $cmd $arg";
|
||||
return "";
|
||||
}
|
||||
|
||||
if($msg !~ m/^00(..)(..)(..)(.*)/) { # 00=REQUEST
|
||||
Log3 $ioName, 4, "$ioName: UNKNOWN msg $msg";
|
||||
return "";
|
||||
@@ -1490,7 +1550,7 @@ ZWave_Parse($$@)
|
||||
if($cmd eq 'ZW_ADD_NODE_TO_NETWORK' ||
|
||||
$cmd eq 'ZW_REMOVE_NODE_FROM_NETWORK') {
|
||||
my @vals = ("learnReady", "nodeFound", "slave",
|
||||
"controller", "", "done", "failed");
|
||||
"controller", "protocolDone", "done", "failed");
|
||||
$evt = ($id eq "00" || hex($id)>@vals+1) ? "unknownArg" : $vals[hex($id)-1];
|
||||
if($evt eq "slave" &&
|
||||
$arg =~ m/(..)....(..)..(.*)$/) {
|
||||
@@ -1499,6 +1559,26 @@ ZWave_Parse($$@)
|
||||
if($cmd eq 'ZW_ADD_NODE_TO_NETWORK');
|
||||
}
|
||||
|
||||
if($evt eq "protocolDone" && $arg =~ m/(..)../) {# done comes at addNode off
|
||||
delete $iodev->{secInitName};
|
||||
my $dh = $modules{ZWave}{defptr}{"$homeId $1"};
|
||||
return "" if(!$dh);
|
||||
|
||||
$dh->{lastMsgTimestamp} = time();
|
||||
my $classes = AttrVal($dh->{NAME}, "classes", "");
|
||||
if($classes =~ m/SECURITY/) {
|
||||
my $key = AttrVal($ioName, "networkKey", "");
|
||||
if($key) {
|
||||
$iodev->{secInitName} = $dh->{NAME};
|
||||
return ZWave_securityInit($dh);
|
||||
} else {
|
||||
Log3 $ioName, 2, "No secure inclusion as $ioName has no networkKey";
|
||||
}
|
||||
}
|
||||
return ZWave_execInits($dh, 0);
|
||||
}
|
||||
|
||||
|
||||
} elsif($cmd eq "ZW_APPLICATION_UPDATE" && $arg =~ m/....(..)..(.*)$/) {
|
||||
my ($type6,$classes) = ($1, $2);
|
||||
my $ret = ZWave_SetClasses($homeId, $id, $type6, $classes);
|
||||
|
||||
Reference in New Issue
Block a user