2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-16 04:36:02 +00:00

01_FHEMWEB.pm: return 401 for empty/no CSRF (Forum #67848)

git-svn-id: https://svn.fhem.de/fhem/trunk@13516 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2017-02-25 21:41:18 +00:00
parent f26213c2f0
commit 0669d97685
3 changed files with 64 additions and 28 deletions

View File

@ -94,6 +94,7 @@ my $FW_use_sha = 0;
my $FW_activateInform = 0;
my $FW_lastWebName = ""; # Name of last FHEMWEB instance, for caching
my $FW_lastHashUpdate = 0;
my $FW_httpRetCode = "";
my %FW_csrfTokenCache;
#########################
@ -530,6 +531,7 @@ FW_Read($$)
}
}
$FW_httpRetCode = "200 OK";
my $cacheable = FW_answerCall($arg);
if($cacheable == -1) {
FW_closeConn($hash);
@ -557,7 +559,7 @@ FW_Read($$)
Log3 $FW_wname, 4,
"name: $arg / RL:$length / $FW_RETTYPE / $compressed / $expires";
if( ! FW_addToWritebuffer($hash,
"HTTP/1.1 200 OK\r\n" .
"HTTP/1.1 $FW_httpRetCode\r\n" .
"Content-Length: $length\r\n" .
$expires . $compressed . $FW_headerlines .
"Content-Type: $FW_RETTYPE\r\n\r\n" .
@ -810,6 +812,7 @@ FW_answerCall($)
if($supplied ne $want) {
Log3 $FW_wname, 3, "FHEMWEB $FW_wname CSRF error: $supplied ne $want. ".
"For detals see the csrfToken FHEMWEB attribute";
$FW_httpRetCode = "401 Unauthorized";
return 0;
}
}

View File

@ -1,5 +1,5 @@
var fd_loadedHash={}, fd_loadedList=[], fd_all={}, fd_allCnt, fd_progress=0,
fd_lang, fd_offsets=[], fd_scrolled=0, fd_modLinks={}, csrfToken="";
fd_lang, fd_offsets=[], fd_scrolled=0, fd_modLinks={}, csrfToken="X";
function
@ -19,13 +19,19 @@ fd_status(txt)
function
fd_fC(fn, callback)
{
console.log("fd_fC:"+fn);
var p = location.pathname;
var cmd = p.substr(0,p.indexOf('/doc'))+
'?cmd='+fn+csrfToken+'&XHR=1';
var ax = $.ajax({ cache:false, url:cmd });
ax.done(callback);
ax.fail(function(req, stat, err) {
console.log("FAIL ERR:"+err+" STAT:"+stat);
var cmd = p.substr(0,p.indexOf('/doc'))+'?cmd='+fn+csrfToken+'&XHR=1';
$.ajax({
url:cmd, method:'POST', cache:false, success:callback,
error:function(xhr, status, err) {
if(xhr.status == 401 && csrfToken) {
csrfToken = "";
fd_csrfRefresh(function(){fd_fC(fn, callback)});
} else {
console.log("FAIL ERR:"+xhr.status+" STAT:"+status);
}
}
});
}
@ -151,6 +157,21 @@ loadOtherLang()
loadOneDoc(mname, fd_loadedHash[mname]=="EN" ? "DE" : "EN");
}
function
fd_csrfRefresh(callback)
{
console.log("fd_csrfRefresh");
$.ajax({
url:location.pathname.replace(/docs.*/,'')+"?XHR=1",
success: function(data, textStatus, request){
csrfToken = request.getResponseHeader('x-fhem-csrftoken');
csrfToken = csrfToken ? ("&fwcsrf="+csrfToken) : "";
if(callback)
callback();
}
});
}
$(document).ready(function(){
var p = location.pathname;
fd_lang = p.substring(p.indexOf("commandref")+11,p.indexOf(".html"));
@ -203,10 +224,5 @@ $(document).ready(function(){
setTimeout(checkScroll, 500);
};
$.ajax({
url:(location.pathname+"").replace(/\/docs.commandref.html.*/,"?XHR=1"),
success: function(data, textStatus, request){
csrfToken = request.getResponseHeader('x-fhem-csrftoken');
csrfToken = csrfToken ? ("&fwcsrf="+csrfToken) : "";
}});
fd_csrfRefresh();
});

View File

@ -8,7 +8,7 @@ var FW_serverLastMsg = FW_serverFirstMsg;
var FW_isIE = (navigator.appVersion.indexOf("MSIE") > 0);
var FW_isiOS = navigator.userAgent.match(/(iPad|iPhone|iPod)/);
var FW_scripts = {}, FW_links = {};
var FW_docReady = false, FW_longpollType;
var FW_docReady = false, FW_longpollType, FW_csrfToken;
var FW_root = "/fhem"; // root
var embedLoadRetry = 100;
@ -70,6 +70,7 @@ FW_jqueryReadyFn()
FW_longpollType = $("body").attr("longpoll");
if(FW_longpollType != "0")
setTimeout("FW_longpoll()", 100);
FW_csrfToken = $("body").attr('fwcsrf');
$("a").each(function() { FW_replaceLink(this); })
$("head script").each(function() {
@ -366,29 +367,47 @@ log(txt)
function
addcsrf(arg)
{
var csrf = $("body").attr('fwcsrf');
if(csrf && arg.indexOf('fwcsrf') < 0)
arg += '&fwcsrf='+csrf;
if(FW_csrfToken) {
arg = arg.replace(/&fwcsrf=[^&]*/,'');
arg += '&fwcsrf='+FW_csrfToken;
}
return arg;
}
function
FW_csrfRefresh(callback)
{
log("FW_csrfRefresh");
$.ajax({
url:location.pathname+"?XHR=1",
success: function(data, textStatus, request){
FW_csrfToken = request.getResponseHeader('x-fhem-csrftoken');
if(callback)
callback();
}
});
}
function
FW_cmd(arg, callback)
{
log("FW_cmd:"+arg);
arg = addcsrf(arg);
arg += '&fw_id='+$("body").attr('fw_id');
var req = new XMLHttpRequest();
req.open("POST", arg, true);
req.send(null);
req.onreadystatechange = function(){
if(req.readyState == 4) {
$.ajax({
url:addcsrf(arg)+'&fw_id='+$("body").attr('fw_id'),
method:'POST',
success: function(data, textStatus, req){
if(callback)
callback(req.responseText);
else if(req.responseText)
FW_errmsg(req.responseText, 5000);
},
error:function(xhr, status, err) {
if(xhr.status == 401 && FW_csrfToken) {
FW_csrfToken = "";
FW_csrfRefresh(function(){FW_cmd(arg, callback)});
}
}
}
});
}
function
@ -1470,8 +1489,6 @@ loadScript(sname, callback, force)
}
script.onload = function(){
scriptLoaded();
// if(FW_isiOS) // Fixed in the maintime/not needed with 10.2
// FW_longpoll();
}
}
h.appendChild(script);