summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Angelacos <nangel@tetrasec.net>2007-11-15 21:58:58 +0000
committerNathan Angelacos <nangel@tetrasec.net>2007-11-15 21:58:58 +0000
commit4ec03d0ebb3c191d2344e0e7c8586605dd2d1804 (patch)
tree908a7c0144f5ae6e9b50043a0bb2dc6cf226bba1
parent1b76b8d1389f9609269b5fe14a34afa92a6cec0c (diff)
downloadacf-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.lua51
-rw-r--r--lib/session.lua59
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
+