diff options
author | Nathan Angelacos <nangel@tetrasec.net> | 2007-11-15 21:58:58 +0000 |
---|---|---|
committer | Nathan Angelacos <nangel@tetrasec.net> | 2007-11-15 21:58:58 +0000 |
commit | 4ec03d0ebb3c191d2344e0e7c8586605dd2d1804 (patch) | |
tree | 908a7c0144f5ae6e9b50043a0bb2dc6cf226bba1 | |
parent | 1b76b8d1389f9609269b5fe14a34afa92a6cec0c (diff) | |
download | acf-core-4ec03d0ebb3c191d2344e0e7c8586605dd2d1804.tar.bz2 acf-core-4ec03d0ebb3c191d2344e0e7c8586605dd2d1804.tar.xz |
Session library now records events of notice when an invalid sessionid
is given, and does lazy saves for empty sessions
git-svn-id: svn://svn.alpinelinux.org/acf/core/trunk@309 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r-- | app/acf_www-controller.lua | 51 | ||||
-rw-r--r-- | lib/session.lua | 59 |
2 files changed, 69 insertions, 41 deletions
diff --git a/app/acf_www-controller.lua b/app/acf_www-controller.lua index 13e1482..5f30124 100644 --- a/app/acf_www-controller.lua +++ b/app/acf_www-controller.lua @@ -1,4 +1,4 @@ ---[[ code for the Alpine Configuration WEB framework +--[[ Code for the Alpine Configuration WEB framework see http://wiki.alpinelinux.org Copyright (C) 2007 Nathan Angelacos Licensed under the terms of GPL2 @@ -24,7 +24,7 @@ mvc.on_load = function (self, parent) self.conf.appuri = "http://" .. ENV.HTTP_HOST .. ENV.SCRIPT_NAME self.conf.default_controller = "welcome" self.clientdata = FORM - + self.conf.clientip = ENV.REMOTE_ADDR parent_exception_handler = parent.exception_handler @@ -33,21 +33,21 @@ mvc.on_load = function (self, parent) sessionlib=require ("session") - self.session = {} + self.sessiondata = {} local tempid = "" if self.clientdata.sessionid == nil then - self.session.id = sessionlib.random_hash(512) - tempid = self.session.id + self.sessiondata.id = sessionlib.random_hash(512) + tempid = self.sessiondata.id else - tempid = self.clientdata.sessionid - local timestamp - timestamp, self.session = sessionlib.load_session(self.conf.sessiondir, - self.clientdata.sessionid) + tempid = self.clientdata.sessionid + timestamp, self.sessiondata = + sessionlib.load_session(self.conf.sessiondir, + self.clientdata.sessionid) if timestamp == nil then - -- FIXME ... need to add this function - -- record an invalid sessionid event - self.session.id = tempid + self.sessiondata.id = tempid + sessionlib.record_event(self.conf.sessiondir, + sessionlib.hash_ip_addr(self.conf.clientip)) else --[[ FIXME --- need to write this function @@ -55,9 +55,9 @@ mvc.on_load = function (self, parent) if (timestamp is > 10 minutes old) sessionlib.unlink.session (self.conf.sessiondir, - self.session.id) - self.session = {} - self.session.id = sessionlib.random_hash(512) + self.sessiondata.id) + self.sessiondata = {} + self.sessiondata.id = sessionlib.random_hash(512) generate flash message "Inactivity logout" end ]]-- @@ -67,18 +67,9 @@ end mvc.post_exec = function (self) - if session.id then -- save the session table; however - -- if its just an empty session, don't save it; - -- Doing so could cause a D.O.S. where someone fills - -- disk with invalid sessionid tables - local c = 0 - for k,v in pairs(session) do - c = c + 1 - end - if c > 1 then - sessionlib.save_session(conf.sessiondir, - session.id, session) - end + if sessiondata.id then + sessionlib.save_session(conf.sessiondir, + sessiondata.id, sessiondata) end end @@ -186,7 +177,7 @@ view_resolver = function(self) return function (viewtable) local template = haserl.loadfile (template) - return template ( pageinfo, menu, submenu, viewtable, self.session ) + return template ( pageinfo, menu, submenu, viewtable, self.sessiondata ) end end @@ -207,8 +198,8 @@ exception_handler = function (self, message ) message.prefix .. message.controller .. "/" .. message.action .. (message.extra or "" ) .. "\n") - if self.session.id then - io.write (html.cookie.set("sessionid", self.session.id)) + if self.sessiondata.id then + io.write (html.cookie.set("sessionid", self.sessiondata.id)) else io.write (html.cookie.unset("sessionid")) end diff --git a/lib/session.lua b/lib/session.lua index fc7ecde..149f5aa 100644 --- a/lib/session.lua +++ b/lib/session.lua @@ -1,6 +1,15 @@ -- Session handling routines - written for acf -- Copyright (C) 2007 N. Angelacos - GPL2 License + +--[[ Note that in this library, we use empty (0 byte) files +-- everwhere we can, as they only take up dir entries, not inodes +-- as the tmpfs blocksize is 4K, and under denial of service +-- attacks hundreds or thousands of events can come in each +-- second, we could end up in a disk full condition if we did +-- not take this precaution. +-- ]]-- + module (..., package.seeall) require "posix" @@ -79,31 +88,48 @@ end save_session = function( sessionpath, session, sessiontable) local file = io.open(sessionpath .. "/session." .. session , "w") - if file then - file:write ( "-- This is an ACF session table.\nlocal timestamp=" .. os.time() ) + if file == nil then + return false + end + + local id = sessiontable.id + + -- clear the id key + sessiontable.id = nil + -- count the keys + local count = 0 + for k,v in pairs (sessiontable) do + count = count + 1 + end + -- If the table only has an "id" field, then don't save it + if count > 0 and file then + file:write ( "-- This is an ACF session table.\n") file:write ( "\nlocal " ) file:write ( serialize("s", sessiontable) ) - file:write ( "return timestamp, s\n") - file:close() - return true - else - return false + file:write ( "return s\n") end + file:close() + sessiontable.id=id + return true end -- Loads a session -- Returns a timestamp (when the session data was saved) and the session table. +-- We insert a "id" field from the "session" load_session = function ( sessionpath, session ) + local s = {} -- session can only have b64 characters in it session = string.gsub ( session or "", "[^" .. b64 .. "]", "") if #session == 0 then return nil, {} end - session = sessionpath .. "/session." .. session - if (posix.stat(session)) then - local file = io.open(session) - return dofile(session) + local spath = sessionpath .. "/session." .. session + local ts = posix.stat(spath, "ctime") + if (ts) then + s = dofile(spath) or {} + s.id = session + return ts, s else return nil, {} end @@ -121,3 +147,14 @@ unlink_session = function (sessionpath, session) return nil end + +-- Record an invalid login event +-- ID would typically be an ip address or username +-- the format is lockevent.id.datetime.processid +record_event = function( sessionpath, id ) + local x = io.open (string.format ("%s/lockevent.%s.%s.%s", + sessionpath or "/", id or "", os.time(), + (posix.getpid("pid")) or "" ), "w") + io.close(x) +end + |