From dd4da9d6ea284ac1b79057e86b88fce151f86f3c Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 10 Aug 2014 13:52:25 +0000 Subject: [PATCH] FHEMWEB: csrfToken added git-svn-id: https://svn.fhem.de/fhem/trunk@6388 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/01_FHEMWEB.pm | 67 +++++++++++++++++++++++++--- fhem/www/pgm2/console.js | 3 ++ fhem/www/pgm2/fhemweb.js | 17 ++++++- fhem/www/pgm2/fhemweb_colorpicker.js | 3 +- fhem/www/pgm2/fhemweb_textField.js | 3 +- fhem/www/pgm2/smallscreenstyle.css | 1 + 6 files changed, 84 insertions(+), 10 deletions(-) diff --git a/fhem/FHEM/01_FHEMWEB.pm b/fhem/FHEM/01_FHEMWEB.pm index d5d9a22ca..bdc1b4291 100755 --- a/fhem/FHEM/01_FHEMWEB.pm +++ b/fhem/FHEM/01_FHEMWEB.pm @@ -6,6 +6,7 @@ use strict; use warnings; use TcpServerUtils; use HttpUtils; +use Time::HiRes qw(gettimeofday); ######################### # Forward declaration @@ -54,6 +55,7 @@ use vars qw($MW_dir); # moddir (./FHEM), needed by edit Files in new # structure use vars qw($FW_ME); # webname (default is fhem), used by 97_GROUP/weblink +use vars qw($FW_CSRF); # CSRF Token or empty use vars qw($FW_ss); # is smallscreen, needed by 97_GROUP/95_VIEW use vars qw($FW_tp); # is touchpad (iPad / etc) use vars qw($FW_sp); # stylesheetPrefix @@ -128,6 +130,7 @@ FHEMWEB_Initialize($) JavaScripts SVGcache:1,0 addStateEvent + csrfToken alarmTimeout allowedCommands allowfrom @@ -434,6 +437,8 @@ FW_answerCall($) $FW_RET = ""; $FW_RETTYPE = "text/html; charset=$FW_encoding"; $FW_ME = "/" . AttrVal($FW_wname, "webname", "fhem"); + $FW_CSRF = ($defs{$FW_wname}{CSRFTOKEN} ? + "&fwcsrf=".$defs{$FW_wname}{CSRFTOKEN} : ""); $MW_dir = "$attr{global}{modpath}/FHEM"; $FW_sp = AttrVal($FW_wname, "stylesheetPrefix", ""); @@ -499,7 +504,14 @@ FW_answerCall($) $FW_plotsize = AttrVal($FW_wname, "plotsize", $FW_ss ? "480,160" : $FW_tp ? "640,160" : "800,160"); my ($cmd, $cmddev) = FW_digestCgi($arg); - + if($cmd && $FW_CSRF) { + my $supplied = $FW_webArgs{fwcsrf} ? $FW_webArgs{fwcsrf} : ""; + my $want = $defs{$FW_wname}{CSRFTOKEN}; + if($supplied ne $want) { + Log3 $FW_wname, 3, "FHEMWEB $FW_wname CSRF error: $supplied ne $want"; + return 0; + } + } if($FW_inform) { # Longpoll header if($FW_inform =~ /type=/) { @@ -658,7 +670,8 @@ FW_answerCall($) my $onload = AttrVal($FW_wname, "longpoll", 1) ? "onload=\"FW_delayedStart()\"" : ""; - FW_pO "\n"; + my $csrf= ($FW_CSRF ? "fwcsrf='$defs{$FW_wname}{CSRFTOKEN}'" : ""); + FW_pO "\n"; if($FW_activateInform) { $FW_cmdret = $FW_activateInform = ""; @@ -679,7 +692,7 @@ FW_answerCall($) foreach my $line (@lines) { $FW_cmdret .= "\n" if( $FW_cmdret ); foreach my $word ( split( / /, $line ) ) { - $word = "$word" + $word = "$word" if( $defs{$word} ); $FW_cmdret .= "$word "; } @@ -921,6 +934,7 @@ FW_makeSelect($$$$) FW_pO "
"; FW_pO FW_hidden("detail", $d); + FW_pO FW_hidden("fwcsrf", $defs{$FW_wname}{CSRFTOKEN}) if($FW_CSRF); FW_pO FW_hidden("dev.$cmd$d", $d); FW_pO FW_submit("cmd.$cmd$d", $cmd, $class); FW_pO "
 $d 
"; @@ -967,6 +981,7 @@ FW_doDetail($) FW_pO ""; FW_pO FW_hidden("detail", $d); + FW_pO FW_hidden("fwcsrf", $defs{$FW_wname}{CSRFTOKEN}) if($FW_CSRF); FW_makeSelect($d, "set", FW_widgetOverride($d, getAllSets($d)), "set"); FW_makeSelect($d, "get", FW_widgetOverride($d, getAllGets($d)), "get"); @@ -1156,7 +1171,7 @@ FW_roomOverview($) foreach(my $idx = 0; $idx < @list1; $idx++) { next if(!$list1[$idx]); my $sel = ($list1[$idx] eq $FW_room ? " selected=\"selected\"" : ""); - FW_pO ""; + FW_pO ""; } FW_pO ""; FW_pO ""; @@ -1204,6 +1219,7 @@ FW_roomOverview($) FW_pO '
'; FW_pO ""; FW_pO FW_hidden("room", "$FW_room") if($FW_room); + FW_pO FW_hidden("fwcsrf", $defs{$FW_wname}{CSRFTOKEN}) if($FW_CSRF); FW_pO FW_textfield("cmd", $FW_ss ? 25 : 40, "maininput"); FW_pO ""; FW_pO "
"; @@ -1661,6 +1677,7 @@ FW_style($$) FW_pO FW_textfieldv("saveName", 30, "saveName", $fileName); FW_pO "

"; FW_pO FW_hidden("cmd", "style save $fileName $cfgDB"); + FW_pO FW_hidden("fwcsrf", $defs{$FW_wname}{CSRFTOKEN}) if($FW_CSRF); FW_pO ""; FW_pO ""; @@ -1766,7 +1783,7 @@ FW_pH(@) my ($link, $txt, $td, $class, $doRet,$nonl) = @_; my $ret; - $link = ($link =~ m,^/,) ? $link : "$FW_ME$FW_subdir?$link"; + $link = ($link =~ m,^/,) ? "$link$FW_CSRF" : "$FW_ME$FW_subdir?$link$FW_CSRF"; # Using onclick, as href starts safari in a webapp. # Known issue: the pointer won't change @@ -1796,6 +1813,7 @@ FW_pHPlain(@) $link = "?$link" if($link !~ m+^/+); my $ret = ""; $ret .= "" if($td); + $link .= $FW_CSRF; if($FW_ss || $FW_tp) { $ret .= "$txt"; } else { @@ -1930,6 +1948,20 @@ FW_Attr(@) $modules{FHEMWEB}{AttrList} .= " ".join(" ",@add) if(@add); } + if($a[2] eq "csrfToken" && $a[0] eq "set") { + my $csrf = $a[3]; + if($csrf eq "random") { + my ($x,$y) = gettimeofday(); + $csrf = rand($y)*rand($x); + } + $hash->{CSRFTOKEN} = $csrf; + } + + if($a[2] eq "csrfToken" && $a[0] eq "del") { + delete($hash->{CSRFTOKEN}); + } + + return $retMsg; } @@ -2096,6 +2128,7 @@ FW_makeEdit($$$) FW_pO "
"; FW_pO "
"; FW_pO FW_hidden("detail", $name); + FW_pO FW_hidden("fwcsrf", $defs{$FW_wname}{CSRFTOKEN}) if($FW_CSRF); my $cmd = "modify"; my $ncols = $FW_ss ? 30 : 60; FW_pO "