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:
parent
895c67a932
commit
9f8640f294
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 <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;
|
||||
|
@ -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($)
|
||||
|
59
fhem/fhem.pl
59
fhem/fhem.pl
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user