00_ZWDongle: add random/setNIF/timeouts calls for Security (Forum #37121)

git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@8634 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig
2015-05-25 13:38:18 +00:00
parent f4202f808c
commit d446267f2f
2 changed files with 60 additions and 22 deletions

View File

@@ -34,20 +34,25 @@ my %sets = (
"replaceFailedNode"=> { cmd => "63%02x" }, # ZW_REPLACE_FAILED_NODE "replaceFailedNode"=> { cmd => "63%02x" }, # ZW_REPLACE_FAILED_NODE
"neighborUpdate" => { cmd => "48%02x" }, # ZW_REQUEST_NODE_NEIGHBOR_UPDATE "neighborUpdate" => { cmd => "48%02x" }, # ZW_REQUEST_NODE_NEIGHBOR_UPDATE
"sendNIF" => { cmd => "12%02x05@" },# ZW_SEND_NODE_INFORMATION "sendNIF" => { cmd => "12%02x05@" },# ZW_SEND_NODE_INFORMATION
"setNIF" => { cmd => "03%02x%02x%02x%02x" },
# SERIAL_API_APPL_NODE_INFORMATION
"timeouts" => { cmd => "06%02x%02x"},# SERIAL_API_SET_TIMEOUTS
"reopen" => { cmd => "" }, "reopen" => { cmd => "" },
); );
my %gets = ( my %gets = (
"caps" => "07", # SERIAL_API_GET_CAPABILITIES "caps" => "07", # SERIAL_API_GET_CAPABILITIES
"ctrlCaps" => "05", # ZW_GET_CONTROLLER_CAPS "ctrlCaps" => "05", # ZW_GET_CONTROLLER_CAPS
"nodeInfo" => "41%02x", # ZW_GET_NODE_PROTOCOL_INFO
"isFailedNode" => "62%02x", # ZW_IS_FAILED_NODE
"nodeList" => "02", # SERIAL_API_GET_INIT_DATA
"homeId" => "20", # MEMORY_GET_ID
"version" => "15", # ZW_GET_VERSION
"getVirtualNodes" => "a5", # ZW_GET_VIRTUAL_NODES "getVirtualNodes" => "a5", # ZW_GET_VIRTUAL_NODES
"homeId" => "20", # MEMORY_GET_ID
"isFailedNode" => "62%02x", # ZW_IS_FAILED_NODE
"neighborList" => "80%02x0101", # GET_ROUTING_TABLE_LINE include dead links, "neighborList" => "80%02x0101", # GET_ROUTING_TABLE_LINE include dead links,
# include non-routing neigbors # include non-routing neigbors
"nodeInfo" => "41%02x", # ZW_GET_NODE_PROTOCOL_INFO
"nodeList" => "02", # SERIAL_API_GET_INIT_DATA
"random" => "1c%02x", # ZW_GET_RANDOM
"version" => "15", # ZW_GET_VERSION
"raw" => "%s", # hex "raw" => "%s", # hex
); );
@@ -134,7 +139,7 @@ use vars qw(%zw_type6);
'a6' => 'ZW_IS_VIRTUAL_NODE', 'a6' => 'ZW_IS_VIRTUAL_NODE',
'b6' => 'ZW_WATCHDOG_ENABLE', 'b6' => 'ZW_WATCHDOG_ENABLE',
'b7' => 'ZW_WATCHDOG_DISABLE', 'b7' => 'ZW_WATCHDOG_DISABLE',
'b8' => 'ZW_WATCHDOG_KICK', 'b8' => 'ZW_WATCHDOG_CHECK',
'b9' => 'ZW_SET_EXT_INT_LEVEL', 'b9' => 'ZW_SET_EXT_INT_LEVEL',
'ba' => 'ZW_RF_POWERLEVEL_GET', 'ba' => 'ZW_RF_POWERLEVEL_GET',
'bb' => 'ZW_GET_NEIGHBOR_COUNT', 'bb' => 'ZW_GET_NEIGHBOR_COUNT',
@@ -158,6 +163,7 @@ use vars qw(%zw_type6);
'11' => 'SWITCH_MULTILEVEL', '11' => 'SWITCH_MULTILEVEL',
); );
my $serInit;
sub sub
ZWDongle_Initialize($) ZWDongle_Initialize($)
@@ -264,6 +270,12 @@ ZWDongle_Set($@)
} }
my $cmd = $sets{$type}{cmd}; my $cmd = $sets{$type}{cmd};
my $fb = substr($cmd, 0, 2);
if($fb =~ m/^[0-8A-F]+$/i &&
ReadingsVal($name, "caps","") !~ m/\b$zw_func_id{$fb}\b/) {
return "$type is unsupported by this controller";
}
my $par = $sets{$type}{param}; my $par = $sets{$type}{param};
if($par && !$par->{noArg}) { if($par && !$par->{noArg}) {
return "Unknown argument for $type, choose one of ".join(" ",keys %{$par}) return "Unknown argument for $type, choose one of ".join(" ",keys %{$par})
@@ -302,6 +314,12 @@ ZWDongle_Get($@)
join(" ", map { $gets{$_} =~ m/%/ ? $_ : "$_:noArg" } sort keys %gets) join(" ", map { $gets{$_} =~ m/%/ ? $_ : "$_:noArg" } sort keys %gets)
if(!defined($gets{$type})); if(!defined($gets{$type}));
my $fb = substr($gets{$type}, 0, 2);
if($fb =~ m/^[0-8A-F]+$/i && !$serInit &&
ReadingsVal($name, "caps","") !~ m/\b$zw_func_id{$fb}\b/) {
return "$type is unsupported by this controller";
}
my @ga = split("%", $gets{$type}, -1); my @ga = split("%", $gets{$type}, -1);
my $nargs = int(@ga)-1; my $nargs = int(@ga)-1;
return "get $name $type needs $nargs arguments" if($nargs != int(@a)); return "get $name $type needs $nargs arguments" if($nargs != int(@a));
@@ -311,7 +329,7 @@ ZWDongle_Get($@)
my $out = sprintf($gets{$type}, @a); my $out = sprintf($gets{$type}, @a);
ZWDongle_Write($hash, "00", $out); ZWDongle_Write($hash, "00", $out);
my $re = "^01".substr($out,0,2); # Start with <01><len><01><CMD> my $re = "^01".substr($out,0,2); # Start with <01><len><01><CMD>
my ($err, $ret) = ZWDongle_ReadAnswer($hash, "get $name $type", $re); my ($err, $ret) = ZWDongle_ReadAnswer($hash, $type, $re);
return $err if($err); return $err if($err);
my $msg=""; my $msg="";
@@ -399,6 +417,10 @@ ZWDongle_Get($@)
} }
$msg = join(",", @list); $msg = join(",", @list);
} elsif($type eq "random") { ############################
return "$name: Cannot generate" if($ret !~ m/^011c01(..)(.*)$/);
$msg = $2; @a = ();
} }
$type .= "_".join("_", @a) if(@a); $type .= "_".join("_", @a) if(@a);
@@ -429,11 +451,17 @@ ZWDongle_DoInit($)
{ {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
$serInit = 1;
DevIo_SetHwHandshake($hash) if($hash->{FD}); DevIo_SetHwHandshake($hash) if($hash->{FD});
ZWDongle_Clear($hash); ZWDongle_Clear($hash);
ZWDongle_Get($hash, $name, "devList"); # Make the following query faster (?) ZWDongle_Get($hash, $name, "caps"); $serInit = 0;
ZWDongle_Get($hash, $name, "homeId"); ZWDongle_Get($hash, $name, "homeId");
ZWDongle_Get($hash, $name, ("random", 32)); # Sec relevant
ZWDongle_Set($hash, $name, ("timeouts", 100, 15)); # Sec relevant
ZWDongle_Clear($hash); # Wait, timeouts needs ack
# NODEINFO_LISTENING, Generic Static controller, Specific Static Controller, 0
ZWDongle_Set($hash, $name, ("setNIF", 1, 2, 1, 0)); # Sec relevant (?)
$hash->{PARTIAL} = ""; $hash->{PARTIAL} = "";
$hash->{STATE} = "Initialized"; $hash->{STATE} = "Initialized";
return undef; return undef;
@@ -621,6 +649,22 @@ ZWDongle_Parse($$$)
$hash->{RAWMSG} = $rmsg; $hash->{RAWMSG} = $rmsg;
my %addvals = (RAWMSG => $rmsg); 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); Dispatch($hash, $rmsg, \%addvals);
} }
@@ -732,8 +776,9 @@ ZWDongle_Ready($)
<li>neighborUpdate<br> <li>neighborUpdate<br>
Requests controller to update his routing table which is based on Requests controller to update his routing table which is based on
slave's neighbor list. The update may take significant time to complete. slave's neighbor list. The update may take significant time to complete.
With the event "done" or "failed" ZWDongle will notify the end of the update process. With the event "done" or "failed" ZWDongle will notify the end of the
To read node's neighbor list see neighborList get below.</li> update process. To read node's neighbor list see neighborList get
below.</li>
<li>reopen<br> <li>reopen<br>
First close and then open the device. Used for debugging purposes. First close and then open the device. Used for debugging purposes.
@@ -764,6 +809,10 @@ ZWDongle_Ready($)
Provides insights to actual network topology. Provides insights to actual network topology.
List includes dead links and non-routing neighbors</li> List includes dead links and non-routing neighbors</li>
<li>random N<br>
request N random bytes from the controller.
</li>
<li>raw<br> <li>raw<br>
Send raw data to the controller. Developer only.</li> Send raw data to the controller. Developer only.</li>
</ul> </ul>

View File

@@ -1474,17 +1474,6 @@ ZWave_Parse($$@)
$iodev->{errReported} = 1; $iodev->{errReported} = 1;
return ""; 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);
return "";
}
Log3 $ioName, 4, "$ioName unhandled ANSWER: $cmd $arg";
return "";
}
if($msg !~ m/^00(..)(..)(..)(.*)/) { # 00=REQUEST if($msg !~ m/^00(..)(..)(..)(.*)/) { # 00=REQUEST
Log3 $ioName, 4, "$ioName: UNKNOWN msg $msg"; Log3 $ioName, 4, "$ioName: UNKNOWN msg $msg";
return ""; return "";