2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-20 07:16:03 +00:00

allowed.pm: SecurityCheck cleanup/rewrite, Forum #81509

git-svn-id: https://svn.fhem.de/fhem/trunk@15676 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2017-12-23 19:33:43 +00:00
parent 895c67a932
commit 9f8640f294
6 changed files with 87 additions and 93 deletions

View File

@ -1,5 +1,6 @@
# 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.
- changed: allowed.pm/fhem.pl: SecurityCheck cleanup, Forum #81509
- new: 88_xs1Bridge: New modul to read xs1 EZcontrol
- change: 93_DbRep: V7.0.0, changelog:
- faster exec if no time attribut/aggregation is set

View File

@ -132,7 +132,7 @@ FHEMWEB_Initialize($)
$hash->{AttrFn} = "FW_Attr";
$hash->{DefFn} = "FW_Define";
$hash->{UndefFn} = "FW_Undef";
$hash->{NotifyFn}= ($init_done ? "FW_Notify" : "FW_SecurityCheck");
$hash->{NotifyFn}= "FW_Notify";
$hash->{AsyncOutputFn} = "FW_AsyncOutput";
$hash->{ActivateInformFn} = "FW_ActivateInform";
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
FW_Define($$)
@ -1070,8 +1039,7 @@ FW_answerCall($)
} else {
my $motd = AttrVal("global","motd","none");
if($motd ne "none") {
$motd =~ s/\n/<br>/g;
FW_addContent(">$motd</div");
FW_addContent("><pre class='motd'>$motd</pre></div");
}
}
}

View File

@ -50,6 +50,7 @@ allowed_Define($$)
}
$auth_refresh = 1;
readingsSingleUpdate($hash, "state", "validFor:", 0);
SecurityCheck() if($init_done);
return undef;
}
@ -104,6 +105,7 @@ allowed_Authenticate($$$$)
my $basicAuth = AttrVal($aName, "basicAuth", undef);
delete $cl->{".httpAuthHeader"};
return 0 if(!$basicAuth);
return 2 if(!$param);
my $FW_httpheader = $param;
my $secret = $FW_httpheader->{Authorization};
@ -173,6 +175,7 @@ allowed_Authenticate($$$$)
my $pw = AttrVal($aName, "password", undef);
if(!$pw) {
$pw = AttrVal($aName, "globalpassword", undef);
return 2 if($pw && !defined($param));
$pw = undef if($pw && $cl->{NAME} =~ m/_127.0.0.1_/);
}
return 0 if(!$pw);
@ -244,8 +247,10 @@ allowed_Attr(@)
} else {
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" ||
$attrName eq "password" || $attrName eq "globalpassword") &&
@ -253,6 +258,7 @@ allowed_Attr(@)
foreach my $d (devspec2array("TYPE=(FHEMWEB|telnet)")) {
delete $defs{$d}{Authenticated} if($defs{$d});
}
InternalTimer(1, "SecurityCheck", 0) if($init_done);
}
return undef;
@ -266,11 +272,16 @@ allowed_fhemwebFn($$$$)
my $hash = $defs{$d};
my $vf = $defs{$d}{validFor} ? $defs{$d}{validFor} : "";
my @arr = map { "<input type='checkbox' ".($vf =~ m/\b$_\b/ ? "checked ":"").
"name='$_' class='vfAttr'><label>$_</label>" }
my (@F_arr, @t_arr);
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} }
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';
$("#vfAttr").click(function(){
var names=[];
@ -279,6 +290,15 @@ $("#vfAttr").click(function(){
});
</script>
EOF
$r .= "For ".join(",",@F_arr).
": \"set $d basicAuth &lt;username&gt; &lt;password&gt;\"<br>"
if(@F_arr);
$r .= "For ".join(",",@t_arr).
": \"set $d password &lt;password&gt;\" or".
" \"set $d globalpassword &lt;password&gt;\"<br>"
if(@t_arr);
return $r;
}
1;

View File

@ -20,7 +20,6 @@ telnet_Initialize($)
$hash->{AsyncOutputFn} = "telnet_Output";
$hash->{UndefFn} = "telnet_Undef";
$hash->{AttrFn} = "telnet_Attr";
$hash->{NotifyFn}= "telnet_SecurityCheck";
$hash->{AttrList} = "globalpassword password prompt allowedCommands ".
"allowfrom SSL connectTimeout connectInterval ".
"encoding:utf8,latin1 sslVersion";
@ -57,39 +56,6 @@ CommandTelnetEncoding($$)
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
telnet_ClientConnect($)

View File

@ -94,6 +94,7 @@ sub RefreshAuthList();
sub RemoveInternalTimer($;$);
sub ReplaceEventMap($$$);
sub ResolveDateWildcards($@);
sub SecurityCheck();
sub SemicolonEscape($);
sub SignalHandling();
sub TimeNow();
@ -574,10 +575,6 @@ if($pfn) {
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;
$lastDefChange = 1;
@ -593,25 +590,11 @@ foreach my $d (keys %defs) {
}
}
SecurityCheck();
$fhem_started = time;
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");
Log 0, "Featurelevel: $featurelevel";
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;

View File

@ -248,6 +248,26 @@ FW_jqueryReadyFn()
$(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_inlineModify();
FW_rawDef();