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:
rudolfkoenig
2015-05-25 18:46:05 +00:00
parent e5eb7f8d3b
commit 282c5e746e
2 changed files with 91 additions and 21 deletions

View File

@@ -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;

View File

@@ -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);