From 5a6ee78379dc3c655885db82da028911b662d267 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Wed, 24 Oct 2018 15:37:39 +0000 Subject: [PATCH] 96_allowed.pm: multi-allowed changes (Forum #92423) git-svn-id: https://svn.fhem.de/fhem/trunk@17613 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/96_allowed.pm | 69 +++++++++++++++++++++++++++-------------- fhem/fhem.pl | 14 ++++++++- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 31a813810..994036fee 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -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. + - feature: allowed: multi-allowed changes (Forum #92423) - feature: 93_DbRep: V8.4.0, reduceLog from DbLog integrated into DbRep, sqlCmd/dbValue with textField-long as default, both attributes timeOlderThan / timeDiffToNow can be set, diff --git a/fhem/FHEM/96_allowed.pm b/fhem/FHEM/96_allowed.pm index 8c2abe88f..5565b60a8 100644 --- a/fhem/FHEM/96_allowed.pm +++ b/fhem/FHEM/96_allowed.pm @@ -8,7 +8,7 @@ use vars qw(@FW_httpheader); # HTTP header, line by line use MIME::Base64; my $allowed_haveSha; -sub allowed_CheckBasicAuth($$$$@); +sub allowed_CheckBasicAuth($$$$); ##################################### sub @@ -26,10 +26,11 @@ allowed_Initialize($) allowedCommands allowedDevices allowedDevicesRegexp + allowedIfAuthenticatedByMe:1,0 basicAuth basicAuthExpiry basicAuthMsg - disable:0,1 + disable:1,0 globalpassword password validFor @@ -90,6 +91,9 @@ allowed_Authorize($$$$) } else { return 0 if(!$me->{validFor} || $me->{validFor} !~ m/\b$cl->{NAME}\b/); } + return 0 if(AttrVal($me->{NAME}, "allowedIfAuthenticatedByMe", 0) && + (!$cl->{AuthenticatedBy} || + $cl->{AuthenticatedBy} ne $me->{NAME})); if($type eq "cmd") { return 0 if(!$me->{allowedCommands}); @@ -121,6 +125,13 @@ allowed_Authenticate($$$$) { my ($me, $cl, $param) = @_; + my $doReturn = sub($$){ + my ($r,$a) = @_; + $cl->{AuthenticatedBy} = $me->{NAME} if($r == 1); + $cl->{AuthenticationDeniedBy} = $me->{NAME} if($r == 2 && $a); + return $r; + }; + return 0 if($me->{disabled}); return 0 if(!$me->{validFor} || $me->{validFor} !~ m/\b$cl->{SNAME}\b/); my $aName = $me->{NAME}; @@ -145,7 +156,7 @@ allowed_Authenticate($$$$) } } - my $pwok = (allowed_CheckBasicAuth($me, $cl, $secret, $basicAuth, 0) == 1); + my $pwok = (allowed_CheckBasicAuth($me, $cl, $secret, $basicAuth) == 1); # Add Cookie header ONLY if authentication with basicAuth was succesful if($pwok && (!defined($authcookie) || $secret ne $authcookie)) { @@ -168,12 +179,12 @@ allowed_Authenticate($$$$) } } - return 1 if($pwok); + return &$doReturn(1, 1) if($pwok); my $msg = AttrVal($aName, "basicAuthMsg", "FHEM: login required"); $cl->{".httpAuthHeader"} = "HTTP/1.1 401 Authorization Required\r\n". "WWW-Authenticate: Basic realm=\"$msg\"\r\n"; - return 2; + return &$doReturn(2, $secret); } elsif($cl->{TYPE} eq "telnet") { my $pw = AttrVal($aName, "password", undef); @@ -188,30 +199,31 @@ allowed_Authenticate($$$$) my $password = $param; my $ret = eval $pw; Log3 $aName, 1, "password expression: $@" if($@); - return ($ret ? 1 : 2); + return &$doReturn($ret ? 1 : 2, $param); } elsif($pw =~ m/^SHA256:(.{8}):(.*)$/) { if($allowed_haveSha) { - return (Digest::SHA::sha256_base64("$1:$param") eq $2) ? 1 : 2; + return &$doReturn(Digest::SHA::sha256_base64("$1:$param") eq $2 ? + 1 : 2, $param); } else { Log3 $me, 3, "Cant load Digest::SHA to decode $me->{NAME} beiscAuth"; } } - return ($pw eq $param) ? 1 : 2; + return &$doReturn(($pw eq $param) ? 1 : 2, $param); } else { $param =~ m/^basicAuth:(.*)/ if($param); - return allowed_CheckBasicAuth($me, $cl, $1, - AttrVal($aName,"basicAuth",undef), $param); + return &$doReturn(allowed_CheckBasicAuth($me, $cl, $1, + AttrVal($aName,"basicAuth",undef)), $param); } } sub -allowed_CheckBasicAuth($$$$@) +allowed_CheckBasicAuth($$$$) { - my ($me, $cl, $secret, $basicAuth, $verbose) = @_; + my ($me, $cl, $secret, $basicAuth) = @_; return 0 if(!$basicAuth); @@ -239,8 +251,7 @@ allowed_CheckBasicAuth($$$$@) } } - Log3 $me, 3, "Login denied by $aName for $user via $cl->{NAME}" - if($pwok != 1 && ($verbose || $user)); + $cl->{AuthenticatedUser} = $user if($user); return $pwok; } @@ -427,18 +438,15 @@ EOF
-
  • allowedDevices
    - Comma separated list of device names which can be manipulated via the - frontends specified by validFor. The regexp is prepended with ^ and - suffixed with $, as usual. Only devices listed in allowedDevices or - matching allowedDevicesRegexp may manipulated. +
  • allowedDevicesRegexp
    + Regexp to match the devicenames, which can be manipulated. The regexp + is prepended with ^ and suffixed with $, as usual.

  • - -
  • allowedDevicesRegexp
    - A regexp to match device names which can be manipulated via the - frontends specified by validFor. Only devices listed in allowedDevices - or matching allowedDevicesRegexp may manipulated. + +
  • allowedIfAuthenticatedByMe
    + if set (to 1), then the allowed parameters will only be checked, if the + authentication was executed by this allowed instance.

  • @@ -581,6 +589,19 @@ EOF Frontend (siehe validFor) geändert werden können.
    + +
  • allowedDevicesRegexp
    + Regexp um die Geräte zu spezifizieren, die man bearbeiten darf. + Das Regexp wird (wie in FHEM üblich) mit ^ und $ ergänzt. +

  • + + +
  • allowedIfAuthenticatedByMe
    + falls gesetzt (auf 1), dann werden die allowed Attribute nur dann + angewendet, falls auch die Authentifikation durch diese allowed Instanz + durchgeführt wurde. +

  • +
  • basicAuth, basicAuthMsg
    Erzwingt eine Authentifizierung mit Benutzername/Passwort für die diff --git a/fhem/fhem.pl b/fhem/fhem.pl index d0dab7d97..5338cc0b3 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -5390,8 +5390,20 @@ Authenticate($$) foreach my $a (@authenticate) { my $r = CallFn($a, "AuthenticateFn", $defs{$a}, $cl, $arg); $needed = $r if($r); - return $r if($r == 1); + last if($r == 1); } + + if($needed == 2 && $cl->{NAME} ne "SecurityCheck") { + my $adb = $cl->{AuthenticationDeniedBy}; + if($adb) { + my $au = $cl->{AuthenticatedUser}; + Log3 $adb, 3, "Login denied ". + ($au ? "for user >$au< ":"")."via $cl->{NAME}"; + } + } else { + delete $cl->{AuthenticationDeniedBy}; + } + return $needed; }