96_allowed.pm 19 KB

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