luci-base: prevent UCI changes in CBI if form is not in submit state

Only process submitted data if the "cbi.submit" parameter is present as the
dispatcher will verify the integrity of the CSRF token in this case.

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
This commit is contained in:
Jo-Philipp Wich 2015-10-07 21:44:46 +02:00
parent 281d2f6178
commit bd504f552d

View file

@ -367,63 +367,64 @@ end
-- Use optimized UCI writing -- Use optimized UCI writing
function Map.parse(self, readinput, ...) function Map.parse(self, readinput, ...)
self.readinput = (readinput ~= false)
self:_run_hooks("on_parse")
if self:formvalue("cbi.skip") then if self:formvalue("cbi.skip") then
self.state = FORM_SKIP self.state = FORM_SKIP
elseif not self.save then
self.state = FORM_INVALID
elseif not self:submitstate() then
self.state = FORM_NODATA
end
-- Back out early to prevent unauthorized changes on the subsequent parse
if self.state ~= nil then
return self:state_handler(self.state) return self:state_handler(self.state)
end end
self.readinput = (readinput ~= false)
self:_run_hooks("on_parse")
Node.parse(self, ...) Node.parse(self, ...)
if self.save then self:_run_hooks("on_save", "on_before_save")
self:_run_hooks("on_save", "on_before_save") for i, config in ipairs(self.parsechain) do
self.uci:save(config)
end
self:_run_hooks("on_after_save")
if (not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply") then
self:_run_hooks("on_before_commit")
for i, config in ipairs(self.parsechain) do for i, config in ipairs(self.parsechain) do
self.uci:save(config) self.uci:commit(config)
end
self:_run_hooks("on_after_save")
if self:submitstate() and ((not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply")) then
self:_run_hooks("on_before_commit")
for i, config in ipairs(self.parsechain) do
self.uci:commit(config)
-- Refresh data because commit changes section names -- Refresh data because commit changes section names
self.uci:load(config) self.uci:load(config)
end end
self:_run_hooks("on_commit", "on_after_commit", "on_before_apply") self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
if self.apply_on_parse then if self.apply_on_parse then
self.uci:apply(self.parsechain) self.uci:apply(self.parsechain)
self:_run_hooks("on_apply", "on_after_apply") self:_run_hooks("on_apply", "on_after_apply")
else else
-- This is evaluated by the dispatcher and delegated to the -- This is evaluated by the dispatcher and delegated to the
-- template which in turn fires XHR to perform the actual -- template which in turn fires XHR to perform the actual
-- apply actions. -- apply actions.
self.apply_needed = true self.apply_needed = true
end end
-- Reparse sections -- Reparse sections
Node.parse(self, true) Node.parse(self, true)
end
end for i, config in ipairs(self.parsechain) do
for i, config in ipairs(self.parsechain) do self.uci:unload(config)
self.uci:unload(config) end
end if type(self.commit_handler) == "function" then
if type(self.commit_handler) == "function" then self:commit_handler(self:submitstate())
self:commit_handler(self:submitstate())
end
end end
if self:submitstate() then if self.proceed then
if not self.save then self.state = FORM_PROCEED
self.state = FORM_INVALID elseif self.changed then
elseif self.proceed then self.state = FORM_CHANGED
self.state = FORM_PROCEED
else
self.state = self.changed and FORM_CHANGED or FORM_VALID
end
else else
self.state = FORM_NODATA self.state = FORM_VALID
end end
return self:state_handler(self.state) return self:state_handler(self.state)