mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
allowed.pm: SecurityCheck cleanup/rewrite, Forum #81509
git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@15676 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4c04e02a37
commit
f575dafe55
1
CHANGED
1
CHANGED
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- changed: allowed.pm/fhem.pl: SecurityCheck cleanup, Forum #81509
|
||||||
- new: 88_xs1Bridge: New modul to read xs1 EZcontrol
|
- new: 88_xs1Bridge: New modul to read xs1 EZcontrol
|
||||||
- change: 93_DbRep: V7.0.0, changelog:
|
- change: 93_DbRep: V7.0.0, changelog:
|
||||||
- faster exec if no time attribut/aggregation is set
|
- faster exec if no time attribut/aggregation is set
|
||||||
|
@ -132,7 +132,7 @@ FHEMWEB_Initialize($)
|
|||||||
$hash->{AttrFn} = "FW_Attr";
|
$hash->{AttrFn} = "FW_Attr";
|
||||||
$hash->{DefFn} = "FW_Define";
|
$hash->{DefFn} = "FW_Define";
|
||||||
$hash->{UndefFn} = "FW_Undef";
|
$hash->{UndefFn} = "FW_Undef";
|
||||||
$hash->{NotifyFn}= ($init_done ? "FW_Notify" : "FW_SecurityCheck");
|
$hash->{NotifyFn}= "FW_Notify";
|
||||||
$hash->{AsyncOutputFn} = "FW_AsyncOutput";
|
$hash->{AsyncOutputFn} = "FW_AsyncOutput";
|
||||||
$hash->{ActivateInformFn} = "FW_ActivateInform";
|
$hash->{ActivateInformFn} = "FW_ActivateInform";
|
||||||
no warnings 'qw';
|
no warnings 'qw';
|
||||||
@ -226,37 +226,6 @@ FHEMWEB_Initialize($)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################################
|
|
||||||
sub
|
|
||||||
FW_SecurityCheck($$)
|
|
||||||
{
|
|
||||||
my ($ntfy, $dev) = @_;
|
|
||||||
return if($dev->{NAME} ne "global" ||
|
|
||||||
!grep(m/^INITIALIZED$/, @{$dev->{CHANGED}}));
|
|
||||||
my $motd = AttrVal("global", "motd", "");
|
|
||||||
if($motd =~ "^SecurityCheck") {
|
|
||||||
my @list1 = devspec2array("TYPE=FHEMWEB");
|
|
||||||
my @list2 = devspec2array("TYPE=allowed");
|
|
||||||
my @list3;
|
|
||||||
for my $l (@list1) { # This is a hack, as hardcoded to basicAuth
|
|
||||||
next if(!$defs{$l});
|
|
||||||
my $fnd = 0;
|
|
||||||
for my $a (@list2) {
|
|
||||||
next if(!$defs{$a});
|
|
||||||
my $vf = AttrVal($a, "validFor","");
|
|
||||||
$fnd = 1 if($vf && ($vf =~ m/\b$l\b/) && AttrVal($a, "basicAuth",""));
|
|
||||||
}
|
|
||||||
push @list3, $l if(!$fnd);
|
|
||||||
}
|
|
||||||
$motd .= (join(",", sort @list3).
|
|
||||||
" has no associated allowed device with basicAuth.\n")
|
|
||||||
if(@list3);
|
|
||||||
$attr{global}{motd} = $motd;
|
|
||||||
}
|
|
||||||
$modules{FHEMWEB}{NotifyFn}= "FW_Notify";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
FW_Define($$)
|
FW_Define($$)
|
||||||
@ -1070,8 +1039,7 @@ FW_answerCall($)
|
|||||||
} else {
|
} else {
|
||||||
my $motd = AttrVal("global","motd","none");
|
my $motd = AttrVal("global","motd","none");
|
||||||
if($motd ne "none") {
|
if($motd ne "none") {
|
||||||
$motd =~ s/\n/<br>/g;
|
FW_addContent("><pre class='motd'>$motd</pre></div");
|
||||||
FW_addContent(">$motd</div");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ allowed_Define($$)
|
|||||||
}
|
}
|
||||||
$auth_refresh = 1;
|
$auth_refresh = 1;
|
||||||
readingsSingleUpdate($hash, "state", "validFor:", 0);
|
readingsSingleUpdate($hash, "state", "validFor:", 0);
|
||||||
|
SecurityCheck() if($init_done);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +105,7 @@ allowed_Authenticate($$$$)
|
|||||||
my $basicAuth = AttrVal($aName, "basicAuth", undef);
|
my $basicAuth = AttrVal($aName, "basicAuth", undef);
|
||||||
delete $cl->{".httpAuthHeader"};
|
delete $cl->{".httpAuthHeader"};
|
||||||
return 0 if(!$basicAuth);
|
return 0 if(!$basicAuth);
|
||||||
|
return 2 if(!$param);
|
||||||
|
|
||||||
my $FW_httpheader = $param;
|
my $FW_httpheader = $param;
|
||||||
my $secret = $FW_httpheader->{Authorization};
|
my $secret = $FW_httpheader->{Authorization};
|
||||||
@ -173,6 +175,7 @@ allowed_Authenticate($$$$)
|
|||||||
my $pw = AttrVal($aName, "password", undef);
|
my $pw = AttrVal($aName, "password", undef);
|
||||||
if(!$pw) {
|
if(!$pw) {
|
||||||
$pw = AttrVal($aName, "globalpassword", undef);
|
$pw = AttrVal($aName, "globalpassword", undef);
|
||||||
|
return 2 if($pw && !defined($param));
|
||||||
$pw = undef if($pw && $cl->{NAME} =~ m/_127.0.0.1_/);
|
$pw = undef if($pw && $cl->{NAME} =~ m/_127.0.0.1_/);
|
||||||
}
|
}
|
||||||
return 0 if(!$pw);
|
return 0 if(!$pw);
|
||||||
@ -244,8 +247,10 @@ allowed_Attr(@)
|
|||||||
} else {
|
} else {
|
||||||
delete($hash->{$attrName});
|
delete($hash->{$attrName});
|
||||||
}
|
}
|
||||||
readingsSingleUpdate($hash, "state", "validFor:".join(",",@param), 1)
|
if($attrName eq "validFor") {
|
||||||
if($attrName eq "validFor");
|
readingsSingleUpdate($hash, "state", "validFor:".join(",",@param), 1);
|
||||||
|
InternalTimer(1, "SecurityCheck", 0) if($init_done);
|
||||||
|
}
|
||||||
|
|
||||||
} elsif(($attrName eq "basicAuth" ||
|
} elsif(($attrName eq "basicAuth" ||
|
||||||
$attrName eq "password" || $attrName eq "globalpassword") &&
|
$attrName eq "password" || $attrName eq "globalpassword") &&
|
||||||
@ -253,6 +258,7 @@ allowed_Attr(@)
|
|||||||
foreach my $d (devspec2array("TYPE=(FHEMWEB|telnet)")) {
|
foreach my $d (devspec2array("TYPE=(FHEMWEB|telnet)")) {
|
||||||
delete $defs{$d}{Authenticated} if($defs{$d});
|
delete $defs{$d}{Authenticated} if($defs{$d});
|
||||||
}
|
}
|
||||||
|
InternalTimer(1, "SecurityCheck", 0) if($init_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
@ -266,11 +272,16 @@ allowed_fhemwebFn($$$$)
|
|||||||
my $hash = $defs{$d};
|
my $hash = $defs{$d};
|
||||||
|
|
||||||
my $vf = $defs{$d}{validFor} ? $defs{$d}{validFor} : "";
|
my $vf = $defs{$d}{validFor} ? $defs{$d}{validFor} : "";
|
||||||
my @arr = map { "<input type='checkbox' ".($vf =~ m/\b$_\b/ ? "checked ":"").
|
my (@F_arr, @t_arr);
|
||||||
"name='$_' class='vfAttr'><label>$_</label>" }
|
my @arr = map {
|
||||||
|
push(@F_arr, $_) if($defs{$_}{TYPE} eq "FHEMWEB");
|
||||||
|
push(@t_arr, $_) if($defs{$_}{TYPE} eq "telnet");
|
||||||
|
"<input type='checkbox' ".($vf =~ m/\b$_\b/ ? "checked ":"").
|
||||||
|
"name='$_' class='vfAttr'><label>$_</label>"
|
||||||
|
}
|
||||||
grep { !$defs{$_}{SNAME} }
|
grep { !$defs{$_}{SNAME} }
|
||||||
devspec2array("TYPE=(FHEMWEB|telnet)");
|
devspec2array("TYPE=(FHEMWEB|telnet)");
|
||||||
return "<input id='vfAttr' type='button' value='attr'> $d validFor <ul>".
|
my $r = "<input id='vfAttr' type='button' value='attr'> $d validFor <ul>".
|
||||||
join("<br>",@arr)."</ul><script>var dev='$d';".<<'EOF';
|
join("<br>",@arr)."</ul><script>var dev='$d';".<<'EOF';
|
||||||
$("#vfAttr").click(function(){
|
$("#vfAttr").click(function(){
|
||||||
var names=[];
|
var names=[];
|
||||||
@ -279,6 +290,15 @@ $("#vfAttr").click(function(){
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
$r .= "For ".join(",",@F_arr).
|
||||||
|
": \"set $d basicAuth <username> <password>\"<br>"
|
||||||
|
if(@F_arr);
|
||||||
|
$r .= "For ".join(",",@t_arr).
|
||||||
|
": \"set $d password <password>\" or".
|
||||||
|
" \"set $d globalpassword <password>\"<br>"
|
||||||
|
if(@t_arr);
|
||||||
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -20,7 +20,6 @@ telnet_Initialize($)
|
|||||||
$hash->{AsyncOutputFn} = "telnet_Output";
|
$hash->{AsyncOutputFn} = "telnet_Output";
|
||||||
$hash->{UndefFn} = "telnet_Undef";
|
$hash->{UndefFn} = "telnet_Undef";
|
||||||
$hash->{AttrFn} = "telnet_Attr";
|
$hash->{AttrFn} = "telnet_Attr";
|
||||||
$hash->{NotifyFn}= "telnet_SecurityCheck";
|
|
||||||
$hash->{AttrList} = "globalpassword password prompt allowedCommands ".
|
$hash->{AttrList} = "globalpassword password prompt allowedCommands ".
|
||||||
"allowfrom SSL connectTimeout connectInterval ".
|
"allowfrom SSL connectTimeout connectInterval ".
|
||||||
"encoding:utf8,latin1 sslVersion";
|
"encoding:utf8,latin1 sslVersion";
|
||||||
@ -57,39 +56,6 @@ CommandTelnetEncoding($$)
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################################
|
|
||||||
sub
|
|
||||||
telnet_SecurityCheck($$)
|
|
||||||
{
|
|
||||||
my ($ntfy, $dev) = @_;
|
|
||||||
return if($dev->{NAME} ne "global" ||
|
|
||||||
!grep(m/^INITIALIZED$/, @{$dev->{CHANGED}}));
|
|
||||||
my $motd = AttrVal("global", "motd", "");
|
|
||||||
if($motd =~ "^SecurityCheck") {
|
|
||||||
my @list1 = devspec2array("TYPE=telnet");
|
|
||||||
my @list2 = devspec2array("TYPE=allowed");
|
|
||||||
my @list3;
|
|
||||||
for my $l (@list1) { # This is a hack, as hardcoded to basicAuth
|
|
||||||
next if(!$defs{$l} || $defs{$l}{TEMPORARY}); # Blocking.pm /Forum #47022
|
|
||||||
my $fnd = 0;
|
|
||||||
for my $a (@list2) {
|
|
||||||
next if(!$defs{$a});
|
|
||||||
my $vf = AttrVal($a, "validFor","");
|
|
||||||
$fnd = 1 if(($vf && $vf =~ m/\b$l\b/) &&
|
|
||||||
(AttrVal($a, "password","") ||
|
|
||||||
AttrVal($a, "globalpassword","")));
|
|
||||||
}
|
|
||||||
push @list3, $l if(!$fnd);
|
|
||||||
}
|
|
||||||
$motd .= (join(",", sort @list3).
|
|
||||||
" has no associated allowed device with password/globalpassword.\n")
|
|
||||||
if(@list3);
|
|
||||||
$attr{global}{motd} = $motd;
|
|
||||||
}
|
|
||||||
delete $modules{telnet}{NotifyFn};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
sub
|
sub
|
||||||
telnet_ClientConnect($)
|
telnet_ClientConnect($)
|
||||||
|
59
fhem.pl
59
fhem.pl
@ -94,6 +94,7 @@ sub RefreshAuthList();
|
|||||||
sub RemoveInternalTimer($;$);
|
sub RemoveInternalTimer($;$);
|
||||||
sub ReplaceEventMap($$$);
|
sub ReplaceEventMap($$$);
|
||||||
sub ResolveDateWildcards($@);
|
sub ResolveDateWildcards($@);
|
||||||
|
sub SecurityCheck();
|
||||||
sub SemicolonEscape($);
|
sub SemicolonEscape($);
|
||||||
sub SignalHandling();
|
sub SignalHandling();
|
||||||
sub TimeNow();
|
sub TimeNow();
|
||||||
@ -574,10 +575,6 @@ if($pfn) {
|
|||||||
close(PID);
|
close(PID);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $sc_text = "SecurityCheck:";
|
|
||||||
$attr{global}{motd} = "$sc_text\n\n"
|
|
||||||
if(!$attr{global}{motd} || $attr{global}{motd} =~ m/^$sc_text/);
|
|
||||||
|
|
||||||
$init_done = 1;
|
$init_done = 1;
|
||||||
$lastDefChange = 1;
|
$lastDefChange = 1;
|
||||||
|
|
||||||
@ -593,25 +590,11 @@ foreach my $d (keys %defs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SecurityCheck();
|
||||||
|
|
||||||
$fhem_started = time;
|
$fhem_started = time;
|
||||||
DoTrigger("global", "INITIALIZED", 1);
|
DoTrigger("global", "INITIALIZED", 1);
|
||||||
|
|
||||||
$attr{global}{motd} .= "Running with root privileges."
|
|
||||||
if($^O !~ m/Win/ && $<==0 && $attr{global}{motd} =~ m/^$sc_text/);
|
|
||||||
$attr{global}{motd} .=
|
|
||||||
"\nRestart FHEM for a new check if the problem is fixed,\n".
|
|
||||||
"or set the global attribute motd to none to supress this message.\n"
|
|
||||||
if($attr{global}{motd} =~ m/^$sc_text\n\n./);
|
|
||||||
my $motd = $attr{global}{motd};
|
|
||||||
if($motd eq "$sc_text\n\n") {
|
|
||||||
delete($attr{global}{motd});
|
|
||||||
} else {
|
|
||||||
if($motd ne "none") {
|
|
||||||
$motd =~ s/\n/ /g;
|
|
||||||
Log 2, $motd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $osuser = "os:$^O user:".(getlogin || getpwuid($<) || "unknown");
|
my $osuser = "os:$^O user:".(getlogin || getpwuid($<) || "unknown");
|
||||||
Log 0, "Featurelevel: $featurelevel";
|
Log 0, "Featurelevel: $featurelevel";
|
||||||
Log 0, "Server started with ".int(keys %defs).
|
Log 0, "Server started with ".int(keys %defs).
|
||||||
@ -5364,4 +5347,40 @@ restoreDir_saveFile($$)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
SecurityCheck()
|
||||||
|
{
|
||||||
|
return if(AttrVal("global", "motd", "") eq "none");
|
||||||
|
my @fnd;
|
||||||
|
foreach my $sdev (devspec2array("TYPE=(telnet|FHEMWEB)")) {
|
||||||
|
next if(!$defs{$sdev} || $defs{$sdev}{TEMPORARY});
|
||||||
|
my $hash = { SNAME=>$sdev, TYPE=>$defs{$sdev}{TYPE} };
|
||||||
|
push(@fnd, " $sdev is not password protected")
|
||||||
|
if(!Authenticate($hash, undef));
|
||||||
|
}
|
||||||
|
if(@fnd) {
|
||||||
|
push @fnd, "";
|
||||||
|
my @l = devspec2array("TYPE=allowed");
|
||||||
|
if(@l) {
|
||||||
|
push @fnd, "Protect this FHEM installation by ".
|
||||||
|
"configuring the allowed device $l[0]";
|
||||||
|
} else {
|
||||||
|
push @fnd, "Protect this FHEM installation by ".
|
||||||
|
"defining an allowed device with define allowed allowed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($^O !~ m/Win/ && $<==0) {
|
||||||
|
push(@fnd, "Running with root privileges is discouraged.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(@fnd) {
|
||||||
|
unshift(@fnd, "SecurityCheck:");
|
||||||
|
push(@fnd, "You can disable this message with attr global motd none");
|
||||||
|
$attr{global}{motd} = join("\n", @fnd);
|
||||||
|
} elsif($attr{global}{motd} =~ m/^SecurityCheck/) {
|
||||||
|
delete $attr{global}{motd};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -248,6 +248,26 @@ FW_jqueryReadyFn()
|
|||||||
$(this).data('delayTimer', wait);
|
$(this).data('delayTimer', wait);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("pre.motd").each(function(){ // add links for passwort setting
|
||||||
|
var txt = $(this).text();
|
||||||
|
txt = txt.replace(/(configuring|define|attr) .*/g, function(x) {
|
||||||
|
return "<a href='#'>"+x+"</a>";
|
||||||
|
});
|
||||||
|
$(this).html(txt);
|
||||||
|
$(this).find("a").click(function(){
|
||||||
|
var txt = $(this).text();
|
||||||
|
var ma = txt.match(/configuring.*device (.*)/);
|
||||||
|
if(ma)
|
||||||
|
location.href = FW_root+"?detail="+ma[1];
|
||||||
|
FW_cmd(FW_root+"?cmd="+encodeURIComponent(txt)+"&XHR=1",
|
||||||
|
function(data){
|
||||||
|
if(txt.indexOf("attr") == 0) $("pre.motd").html("");
|
||||||
|
if(txt.indexOf("define") == 0)
|
||||||
|
location.href = FW_root+"?detail=allowed";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
FW_smallScreenCommands();
|
FW_smallScreenCommands();
|
||||||
FW_inlineModify();
|
FW_inlineModify();
|
||||||
FW_rawDef();
|
FW_rawDef();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user