96_allowed.pm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. ##############################################
  2. # $Id: 96_allowed.pm 17613 2018-10-24 15:37:39Z rudolfkoenig $
  3. package main;
  4. use strict;
  5. use warnings;
  6. use vars qw(@FW_httpheader); # HTTP header, line by line
  7. use MIME::Base64;
  8. my $allowed_haveSha;
  9. sub allowed_CheckBasicAuth($$$$);
  10. #####################################
  11. sub
  12. allowed_Initialize($)
  13. {
  14. my ($hash) = @_;
  15. $hash->{DefFn} = "allowed_Define";
  16. $hash->{AuthorizeFn} = "allowed_Authorize";
  17. $hash->{AuthenticateFn} = "allowed_Authenticate";
  18. $hash->{SetFn} = "allowed_Set";
  19. $hash->{AttrFn} = "allowed_Attr";
  20. no warnings 'qw';
  21. my @attrList = qw(
  22. allowedCommands
  23. allowedDevices
  24. allowedDevicesRegexp
  25. allowedIfAuthenticatedByMe:1,0
  26. basicAuth
  27. basicAuthExpiry
  28. basicAuthMsg
  29. disable:1,0
  30. globalpassword
  31. password
  32. validFor
  33. );
  34. use warnings 'qw';
  35. $hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
  36. $hash->{UndefFn} = "allowed_Undef";
  37. $hash->{FW_detailFn} = "allowed_fhemwebFn";
  38. eval { require Digest::SHA; };
  39. if($@) {
  40. Log3 $hash, 4, $@;
  41. $allowed_haveSha = 0;
  42. } else {
  43. $allowed_haveSha = 1;
  44. }
  45. }
  46. #####################################
  47. sub
  48. allowed_Define($$)
  49. {
  50. my ($hash, $def) = @_;
  51. my @l = split(" ", $def);
  52. if(@l > 2) {
  53. my %list;
  54. for(my $i=2; $i<@l; $i++) {
  55. $list{$l[$i]} = 1;
  56. }
  57. $hash->{devices} = \%list;
  58. }
  59. $auth_refresh = 1;
  60. readingsSingleUpdate($hash, "state", "validFor:", 0);
  61. SecurityCheck() if($init_done);
  62. return undef;
  63. }
  64. sub
  65. allowed_Undef($$)
  66. {
  67. $auth_refresh = 1;
  68. return undef;
  69. }
  70. #####################################
  71. # Return 0 for don't care, 1 for Allowed, 2 for forbidden.
  72. sub
  73. allowed_Authorize($$$$)
  74. {
  75. my ($me, $cl, $type, $arg) = @_;
  76. return 0 if($me->{disabled});
  77. if( $cl->{SNAME} ) {
  78. return 0 if(!$me->{validFor} || $me->{validFor} !~ m/\b$cl->{SNAME}\b/);
  79. } else {
  80. return 0 if(!$me->{validFor} || $me->{validFor} !~ m/\b$cl->{NAME}\b/);
  81. }
  82. return 0 if(AttrVal($me->{NAME}, "allowedIfAuthenticatedByMe", 0) &&
  83. (!$cl->{AuthenticatedBy} ||
  84. $cl->{AuthenticatedBy} ne $me->{NAME}));
  85. if($type eq "cmd") {
  86. return 0 if(!$me->{allowedCommands});
  87. # Return 0: allow stacking with other instances, see Forum#46380
  88. return 0 if($me->{allowedCommands} =~ m/\b\Q$arg\E\b/);
  89. Log3 $me, 3, "Forbidden command $arg for $cl->{NAME}";
  90. stacktrace() if(AttrVal($me, "verbose", 5));
  91. return 2;
  92. }
  93. if($type eq "devicename") {
  94. return 0 if(!$me->{allowedDevices} &&
  95. !$me->{allowedDevicesRegexp});
  96. return 1 if($me->{allowedDevices} &&
  97. $me->{allowedDevices} =~ m/\b\Q$arg\E\b/);
  98. return 1 if($me->{allowedDevicesRegexp} &&
  99. $arg =~ m/^$me->{allowedDevicesRegexp}$/);
  100. Log3 $me, 3, "Forbidden device $arg for $cl->{NAME}";
  101. stacktrace() if(AttrVal($me, "verbose", 5));
  102. return 2;
  103. }
  104. return 0;
  105. }
  106. #####################################
  107. # Return 0 for authentication not needed, 1 for auth-ok, 2 for wrong password
  108. sub
  109. allowed_Authenticate($$$$)
  110. {
  111. my ($me, $cl, $param) = @_;
  112. my $doReturn = sub($$){
  113. my ($r,$a) = @_;
  114. $cl->{AuthenticatedBy} = $me->{NAME} if($r == 1);
  115. $cl->{AuthenticationDeniedBy} = $me->{NAME} if($r == 2 && $a);
  116. return $r;
  117. };
  118. return 0 if($me->{disabled});
  119. return 0 if(!$me->{validFor} || $me->{validFor} !~ m/\b$cl->{SNAME}\b/);
  120. my $aName = $me->{NAME};
  121. if($cl->{TYPE} eq "FHEMWEB") {
  122. my $basicAuth = AttrVal($aName, "basicAuth", undef);
  123. delete $cl->{".httpAuthHeader"};
  124. return 0 if(!$basicAuth);
  125. return 2 if(!$param);
  126. my $FW_httpheader = $param;
  127. my $secret = $FW_httpheader->{Authorization};
  128. $secret =~ s/^Basic //i if($secret);
  129. # Check for Cookie in headers if no basicAuth header is set
  130. my $authcookie;
  131. if (!$secret && $FW_httpheader->{Cookie}) {
  132. if(AttrVal($aName, "basicAuthExpiry", 0)) {
  133. my $cookie = "; ".$FW_httpheader->{Cookie}.";";
  134. $authcookie = $1 if ( $cookie =~ /; AuthToken=([^;]+);/ );
  135. $secret = $authcookie;
  136. }
  137. }
  138. my $pwok = (allowed_CheckBasicAuth($me, $cl, $secret, $basicAuth) == 1);
  139. # Add Cookie header ONLY if authentication with basicAuth was succesful
  140. if($pwok && (!defined($authcookie) || $secret ne $authcookie)) {
  141. my $time = AttrVal($aName, "basicAuthExpiry", 0);
  142. if ( $time ) {
  143. my ($user, $password) = split(":", decode_base64($secret)) if($secret);
  144. $time = int($time*86400+time());
  145. # generate timestamp according to RFC-1130 in Expires
  146. my $expires = FmtDateTimeRFC1123($time);
  147. readingsBeginUpdate($me);
  148. readingsBulkUpdate($me,'lastAuthUser', $user, 1);
  149. readingsBulkUpdate($me,'lastAuthExpires', $time, 1);
  150. readingsBulkUpdate($me,'lastAuthExpiresFmt', $expires, 1);
  151. readingsEndUpdate($me, 1);
  152. # set header with expiry
  153. $cl->{".httpAuthHeader"} = "Set-Cookie: AuthToken=".$secret.
  154. "; Path=/ ; Expires=$expires\r\n" ;
  155. }
  156. }
  157. return &$doReturn(1, 1) if($pwok);
  158. my $msg = AttrVal($aName, "basicAuthMsg", "FHEM: login required");
  159. $cl->{".httpAuthHeader"} = "HTTP/1.1 401 Authorization Required\r\n".
  160. "WWW-Authenticate: Basic realm=\"$msg\"\r\n";
  161. return &$doReturn(2, $secret);
  162. } elsif($cl->{TYPE} eq "telnet") {
  163. my $pw = AttrVal($aName, "password", undef);
  164. if(!$pw) {
  165. $pw = AttrVal($aName, "globalpassword", undef);
  166. $pw = undef if($pw && $cl->{NAME} =~ m/_127.0.0.1_/);
  167. }
  168. return 0 if(!$pw);
  169. return 2 if(!defined($param));
  170. if($pw =~ m/^{.*}$/) {
  171. my $password = $param;
  172. my $ret = eval $pw;
  173. Log3 $aName, 1, "password expression: $@" if($@);
  174. return &$doReturn($ret ? 1 : 2, $param);
  175. } elsif($pw =~ m/^SHA256:(.{8}):(.*)$/) {
  176. if($allowed_haveSha) {
  177. return &$doReturn(Digest::SHA::sha256_base64("$1:$param") eq $2 ?
  178. 1 : 2, $param);
  179. } else {
  180. Log3 $me, 3, "Cant load Digest::SHA to decode $me->{NAME} beiscAuth";
  181. }
  182. }
  183. return &$doReturn(($pw eq $param) ? 1 : 2, $param);
  184. } else {
  185. $param =~ m/^basicAuth:(.*)/ if($param);
  186. return &$doReturn(allowed_CheckBasicAuth($me, $cl, $1,
  187. AttrVal($aName,"basicAuth",undef)), $param);
  188. }
  189. }
  190. sub
  191. allowed_CheckBasicAuth($$$$)
  192. {
  193. my ($me, $cl, $secret, $basicAuth) = @_;
  194. return 0 if(!$basicAuth);
  195. my $aName = $me->{NAME};
  196. my $pwok = ($secret && $secret eq $basicAuth) ? 1 : 2; # Base64
  197. my ($user, $password) = split(":", decode_base64($secret)) if($secret);
  198. ($user,$password) = ("","") if(!defined($user) || !defined($password));
  199. if($secret && $basicAuth =~ m/^{.*}$/) {
  200. $pwok = eval $basicAuth;
  201. if($@) {
  202. Log3 $aName, 1, "basicAuth expression: $@";
  203. $pwok = 2;
  204. } else {
  205. $pwok = ($pwok ? 1 : 2);
  206. }
  207. } elsif($basicAuth =~ m/^SHA256:(.{8}):(.*)$/) {
  208. if($allowed_haveSha) {
  209. $pwok = (Digest::SHA::sha256_base64("$1:$user:$password") eq $2 ? 1 : 2);
  210. } else {
  211. Log3 $me, 3, "Cannot load Digest::SHA to decode $aName basicAuth";
  212. $pwok = 2;
  213. }
  214. }
  215. $cl->{AuthenticatedUser} = $user if($user);
  216. return $pwok;
  217. }
  218. sub
  219. allowed_Set(@)
  220. {
  221. my ($hash, @a) = @_;
  222. my %sets = (globalpassword=>1, password=>1, basicAuth=>2);
  223. return "no set argument specified" if(int(@a) < 2);
  224. return "Unknown argument $a[1], choose one of ".join(" ",sort keys %sets)
  225. if(!defined($sets{$a[1]}));
  226. return "$a[1] needs $sets{$a[1]} parameters"
  227. if(@a-2 != $sets{$a[1]});
  228. return "Cannot load Digest::SHA" if(!$allowed_haveSha);
  229. my $plain = ($a[1] eq "basicAuth" ? "$a[2]:$a[3]" : $a[2]);
  230. my ($x,$y) = gettimeofday();
  231. my $salt = substr(sprintf("%08X", rand($y)*rand($x)),0,8);
  232. CommandAttr($hash->{CL}, "$a[0] $a[1] SHA256:$salt:".
  233. Digest::SHA::sha256_base64("$salt:$plain"));
  234. }
  235. sub
  236. allowed_Attr(@)
  237. {
  238. my ($type, $devName, $attrName, @param) = @_;
  239. my $hash = $defs{$devName};
  240. my $set = ($type eq "del" ? 0 : (!defined($param[0]) || $param[0]) ? 1 : 0);
  241. if($attrName eq "disable") {
  242. readingsSingleUpdate($hash, "state", $set ? "disabled" : "active", 1);
  243. if($set) {
  244. $hash->{disabled} = 1;
  245. } else {
  246. delete($hash->{disabled});
  247. }
  248. } elsif($attrName eq "allowedCommands" || # hoping for some speedup
  249. $attrName eq "allowedDevices" ||
  250. $attrName eq "allowedDevicesRegexp" ||
  251. $attrName eq "validFor") {
  252. if($set) {
  253. $hash->{$attrName} = join(" ", @param);
  254. } else {
  255. delete($hash->{$attrName});
  256. }
  257. if($attrName eq "validFor") {
  258. readingsSingleUpdate($hash, "state", "validFor:".join(",",@param), 1);
  259. InternalTimer(1, "SecurityCheck", 0) if($init_done);
  260. }
  261. } elsif(($attrName eq "basicAuth" ||
  262. $attrName eq "password" || $attrName eq "globalpassword") &&
  263. $type eq "set") {
  264. foreach my $d (devspec2array("TYPE=(FHEMWEB|telnet)")) {
  265. delete $defs{$d}{Authenticated} if($defs{$d});
  266. }
  267. InternalTimer(1, "SecurityCheck", 0) if($init_done);
  268. }
  269. return undef;
  270. }
  271. #########################
  272. sub
  273. allowed_fhemwebFn($$$$)
  274. {
  275. my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
  276. my $hash = $defs{$d};
  277. my $vf = $defs{$d}{validFor} ? $defs{$d}{validFor} : "";
  278. my (@F_arr, @t_arr);
  279. my @arr = map {
  280. my $ca = $modules{$defs{$_}{TYPE}}{CanAuthenticate};
  281. push(@F_arr, $_) if($ca == 1);
  282. push(@t_arr, $_) if($ca == 2);
  283. "<input type='checkbox' ".($vf =~ m/\b$_\b/ ? "checked ":"").
  284. "name='$_' class='vfAttr'><label>$_</label>"
  285. }
  286. grep { !$defs{$_}{SNAME} &&
  287. $modules{$defs{$_}{TYPE}}{CanAuthenticate} }
  288. sort keys %defs;
  289. my $r = "<input id='vfAttr' type='button' value='attr'> $d validFor <ul>".
  290. join("<br>",@arr)."</ul><script>var dev='$d';".<<'EOF';
  291. $("#vfAttr").click(function(){
  292. var names=[];
  293. $("input.vfAttr:checked").each(function(){names.push($(this).attr("name"))});
  294. FW_cmd(FW_root+"?cmd=attr "+dev+" validFor "+names.join(",")+"&XHR=1");
  295. });
  296. </script>
  297. EOF
  298. $r .= "For ".join(",",@F_arr).
  299. ": \"set $d basicAuth &lt;username&gt; &lt;password&gt;\"<br>"
  300. if(@F_arr);
  301. $r .= "For ".join(",",@t_arr).
  302. ": \"set $d password &lt;password&gt;\" or".
  303. " \"set $d globalpassword &lt;password&gt;\"<br>"
  304. if(@t_arr);
  305. return $r;
  306. }
  307. 1;
  308. =pod
  309. =item helper
  310. =item summary authorize command execution based on frontend
  311. =item summary_DE authorisiert Befehlsausf&uuml;hrung basierend auf dem Frontend
  312. =begin html
  313. <a name="allowed"></a>
  314. <h3>allowed</h3>
  315. <ul>
  316. <br>
  317. <a name="alloweddefine"></a>
  318. <b>Define</b>
  319. <ul>
  320. <code>define &lt;name&gt; allowed &lt;deviceList&gt;</code>
  321. <br><br>
  322. Authorize execution of commands and modification of devices based on the
  323. frontend used and/or authenticate users.<br><br>
  324. If there are multiple instances defined which are valid for a given
  325. frontend device, then all authorizations must succeed. For authentication
  326. it is sufficient when one of the instances succeeds. The checks are
  327. executed in alphabetical order of the allowed instance names.<br><br>
  328. <b>Note:</b> this module should work as intended, but no guarantee
  329. can be given that there is no way to circumvent it.<br><br>
  330. Examples:
  331. <ul><code>
  332. define allowedWEB allowed<br>
  333. attr allowedWEB validFor WEB,WEBphone,WEBtablet<br>
  334. attr allowedWEB basicAuth { "$user:$password" eq "admin:secret" }<br>
  335. attr allowedWEB allowedCommands set,get<br><br>
  336. define allowedTelnet allowed<br>
  337. attr allowedTelnet validFor telnetPort<br>
  338. attr allowedTelnet password secret<br>
  339. </code></ul>
  340. <br>
  341. </ul>
  342. <a name="allowedset"></a>
  343. <b>Set</b>
  344. <ul>
  345. <li>basicAuth &lt;username&gt; &lt;password&gt;</li>
  346. <li>password &lt;password&gt;</li>
  347. <li>globalpassword &lt;password&gt;<br>
  348. these commands set the corresponding attribute, by computing an SHA256
  349. hash from the arguments and a salt. Note: the perl module Device::SHA is
  350. needed.
  351. </li>
  352. </ul><br>
  353. <a name="allowedget"></a>
  354. <b>Get</b> <ul>N/A</ul><br>
  355. <a name="allowedattr"></a>
  356. <b>Attributes</b>
  357. <ul>
  358. <li><a href="#disable">disable</a></li><br>
  359. <a name="allowedCommands"></a>
  360. <li>allowedCommands<br>
  361. A comma separated list of commands allowed from the matching frontend
  362. (see validFor).<br>
  363. If set to an empty list <code>, (i.e. comma only)</code>
  364. then no comands are allowed. If set to <code>get,set</code>, then only
  365. a "regular" usage is allowed via set and get, but changing any
  366. configuration is forbidden.<br>
  367. </li><br>
  368. <a name="allowedDevices"></a>
  369. <li>allowedDevices<br>
  370. A comma or space separated list of device names which can be
  371. manipulated via the matching frontend (see validFor).
  372. </li><br>
  373. <a name="allowedDevicesRegexp"></a>
  374. <li>allowedDevicesRegexp<br>
  375. Regexp to match the devicenames, which can be manipulated. The regexp
  376. is prepended with ^ and suffixed with $, as usual.
  377. </li><br>
  378. <a name="allowedIfAuthenticatedByMe"></a>
  379. <li>allowedIfAuthenticatedByMe<br>
  380. if set (to 1), then the allowed parameters will only be checked, if the
  381. authentication was executed by this allowed instance.
  382. </li><br>
  383. <a name="basicAuth"></a>
  384. <li>basicAuth, basicAuthMsg<br>
  385. request a username/password authentication for FHEMWEB access.
  386. It can be a base64 encoded string of user:password, an SHA256 hash
  387. (which should be set via the corresponding set command) or a perl
  388. expression if enclosed in {}, where $user and $password are set, and
  389. which returns true if accepted or false if not. Examples:
  390. <ul><code>
  391. attr allowed basicAuth ZmhlbXVzZXI6c2VjcmV0<br>
  392. attr allowed basicAuth SHA256:F87740B5:q8dHeiClaPLaWVsR/rqkzcBhw/JvvwVi4bEwKmJc/Is<br>
  393. attr allowed basicAuth {"$user:$password" eq "fhemuser:secret"}<br>
  394. </code></ul>
  395. If basicAuthMsg is set, it will be displayed in the popup window when
  396. requesting the username/password. Note: not all browsers support this
  397. feature.<br>
  398. </li><br>
  399. <a name="basicAuthExpiry"></a>
  400. <li>basicAuthExpiry<br>
  401. allow the basicAuth to be kept valid for a given number of days.
  402. So username/password as specified in basicAuth are only requested
  403. after a certain period.
  404. This is achieved by sending a cookie to the browser that will expire
  405. after the given period.
  406. Only valid if basicAuth is set.
  407. </li><br>
  408. <a name="password"></a>
  409. <li>password<br>
  410. Specify a password for telnet instances, which has to be entered as the
  411. very first string after the connection is established. The same rules
  412. apply as for basicAuth, with the expception that there is no user to be
  413. specified.<br>
  414. Note: if this attribute is set, you have to specify a password as the
  415. first argument when using fhem.pl in client mode:
  416. <ul>
  417. perl fhem.pl localhost:7072 secret "set lamp on"
  418. </ul>
  419. </li><br>
  420. <a name="globalpassword"></a>
  421. <li>globalpassword<br>
  422. Just like the attribute password, but a password will only required for
  423. non-local connections.
  424. </li><br>
  425. <a name="validFor"></a>
  426. <li>validFor<br>
  427. A comma separated list of frontend names. Currently supported frontends
  428. are all devices connected through the FHEM TCP/IP library, e.g. telnet
  429. and FHEMWEB. The allowed instance is only active, if this attribute is
  430. set.
  431. </li>
  432. </ul>
  433. <br>
  434. </ul>
  435. =end html
  436. =begin html_DE
  437. <a name="allowed"></a>
  438. <h3>allowed</h3>
  439. <ul>
  440. <br>
  441. <a name="alloweddefine"></a>
  442. <b>Define</b>
  443. <ul>
  444. <code>define &lt;name&gt; allowed &lt;deviceList&gt;</code>
  445. <br><br>
  446. Authorisiert das Ausf&uuml;hren von Kommandos oder das &Auml;ndern von
  447. Ger&auml;ten abh&auml;ngig vom verwendeten Frontend.<br>
  448. Falls man mehrere allowed Instanzen definiert hat, die f&uuml;r dasselbe
  449. Frontend verantwortlich sind, dann m&uuml;ssen alle Authorisierungen
  450. genehmigt sein, um das Befehl ausf&uuml;hren zu k&ouml;nnen. Auf der
  451. anderen Seite reicht es, wenn einer der Authentifizierungen positiv
  452. entschieden wird. Die Pr&uuml;fungen werden in alphabetischer Reihenfolge
  453. der Instanznamen ausgef&uuml;hrt. <br><br>
  454. <b>Achtung:</b> das Modul sollte wie hier beschrieben funktionieren,
  455. allerdings k&ouml;nnen wir keine Garantie geben, da&szlig; man sie nicht
  456. &uuml;berlisten, und Schaden anrichten kann.<br><br>
  457. Beispiele:
  458. <ul><code>
  459. define allowedWEB allowed<br>
  460. attr allowedWEB validFor WEB,WEBphone,WEBtablet<br>
  461. attr allowedWEB basicAuth { "$user:$password" eq "admin:secret" }<br>
  462. attr allowedWEB allowedCommands set,get<br><br>
  463. define allowedTelnet allowed<br>
  464. attr allowedTelnet validFor telnetPort<br>
  465. attr allowedTelnet password secret<br>
  466. </code></ul>
  467. <br>
  468. </ul>
  469. <a name="allowedset"></a>
  470. <b>Set</b>
  471. <ul>
  472. <li>basicAuth &lt;username&gt; &lt;password&gt;</li>
  473. <li>password &lt;password&gt;</li>
  474. <li>globalpassword &lt;password&gt;<br>
  475. diese Befehle setzen das entsprechende Attribut, indem sie aus den
  476. Parameter und ein Salt ein SHA256 Hashwert berechnen. Achtung: das perl
  477. Modul Device::SHA wird ben&ouml;tigt.
  478. </li>
  479. </ul><br>
  480. <a name="allowedget"></a>
  481. <b>Get</b> <ul>N/A</ul><br>
  482. <a name="allowedattr"></a>
  483. <b>Attribute</b>
  484. <ul>
  485. <li><a href="#disable">disable</a>
  486. </li><br>
  487. <a name="allowedCommands"></a>
  488. <li>allowedCommands<br>
  489. Eine Komma getrennte Liste der erlaubten Befehle des passenden
  490. Frontends (siehe validFor). Bei einer leeren Liste (, dh. nur ein
  491. Komma) wird dieser Frontend "read-only".
  492. Falls es auf <code>get,set</code> gesetzt ist, dann sind in dieser
  493. Frontend keine Konfigurations&auml;nderungen m&ouml;glich, nur
  494. "normale" Bedienung der Schalter/etc.
  495. </li><br>
  496. <a name="allowedDevices"></a>
  497. <li>allowedDevices<br>
  498. Komma getrennte Liste von Ger&auml;tenamen, die mit dem passenden
  499. Frontend (siehe validFor) ge&auml;ndert werden k&ouml;nnen.
  500. </li><br>
  501. <a name="allowedDevicesRegexp"></a>
  502. <li>allowedDevicesRegexp<br>
  503. Regexp um die Ger&auml;te zu spezifizieren, die man bearbeiten darf.
  504. Das Regexp wird (wie in FHEM &uuml;blich) mit ^ und $ erg&auml;nzt.
  505. </li><br>
  506. <a name="allowedIfAuthenticatedByMe"></a>
  507. <li>allowedIfAuthenticatedByMe<br>
  508. falls gesetzt (auf 1), dann werden die allowed Attribute nur dann
  509. angewendet, falls auch die Authentifikation durch diese allowed Instanz
  510. durchgef&uuml;hrt wurde.
  511. </li><br>
  512. <a name="basicAuth"></a>
  513. <li>basicAuth, basicAuthMsg<br>
  514. Erzwingt eine Authentifizierung mit Benutzername/Passwort f&uuml;r die
  515. zugerdnete FHEMWEB Instanzen. Der Wert kann entweder das base64
  516. kodierte Benutzername:Passwort sein, ein SHA256 hash (was man am besten
  517. mit dem passenden set Befehl erzeugt), oder, falls er in {}
  518. eingeschlossen ist, ein Perl Ausdruck. F&uuml;r Letzteres wird
  519. $user und $passwort gesetzt, und muss wahr zur&uuml;ckliefern, falls
  520. Benutzername und Passwort korrekt sind. Beispiele:
  521. <ul><code>
  522. attr allowed basicAuth ZmhlbXVzZXI6c2VjcmV0<br>
  523. attr allowed basicAuth SHA256:F87740B5:q8dHeiClaPLaWVsR/rqkzcBhw/JvvwVi4bEwKmJc/Is<br>
  524. attr allowed basicAuth {"$user:$password" eq "fhemuser:secret"}<br>
  525. </code></ul>
  526. basicAuthMsg wird (in manchen Browsern) in dem Passwort Dialog als
  527. &Uuml;berschrift angezeigt.<br>
  528. </li><br>
  529. <a name="password"></a>
  530. <li>password<br>
  531. Betrifft nur telnet Instanzen (siehe validFor): Bezeichnet ein
  532. Passwort, welches als allererster String eingegeben werden muss,
  533. nachdem die Verbindung aufgebaut wurde. F&uuml;r die Werte gelten die
  534. Regeln von basicAuth, mit der Ausnahme, dass nur Passwort und kein
  535. Benutzername spezifiziert wird.<br> Falls dieser Parameter gesetzt
  536. wird, sendet FHEM telnet IAC Requests, um ein Echo w&auml;hrend der
  537. Passworteingabe zu unterdr&uuml;cken. Ebenso werden alle
  538. zur&uuml;ckgegebenen Zeilen mit \r\n abgeschlossen.<br>
  539. Falls dieses Attribut gesetzt wird, muss als erstes Argument ein
  540. Passwort angegeben werden, wenn fhem.pl im Client-mode betrieben wird:
  541. <ul><code>
  542. perl fhem.pl localhost:7072 secret "set lamp on"
  543. </code></ul>
  544. </li><br>
  545. <a name="globalpassword"></a>
  546. <li>globalpassword<br>
  547. Betrifft nur telnet Instanzen (siehe validFor): Entspricht dem
  548. Attribut password; ein Passwort wird aber ausschlie&szlig;lich f&uuml;r
  549. nicht-lokale Verbindungen verlangt.
  550. </li><br>
  551. <a name="validFor"></a>
  552. <li>validFor<br>
  553. Komma separierte Liste von Frontend-Instanznamen. Aktuell werden nur
  554. Frontends unterst&uuml;tzt, die das FHEM TCP/IP Bibliothek verwenden,
  555. z.Bsp. telnet und FHEMWEB. Falls nicht gesetzt, ist die allowed Instanz
  556. nicht aktiv.
  557. </li>
  558. </ul>
  559. <br>
  560. </ul>
  561. =end html_DE
  562. =cut