Mercurial > avadmin > converted
view av_user.py @ 508:64f8666690d8
README update
(Logical change 1.149)
author | optonline.net!jeffpc |
---|---|
date | Fri, 16 Jan 2004 02:53:48 +0000 |
parents | 524a0baf7f24 |
children | 903781c081b7 |
line wrap: on
line source
#/* # * AV Admin - Helps to manage an AV department # * # * Copyright (C) 2003, 2004 Josef "Jeff" Sipek # * # * This program is free software; you can redistribute it and/or modify # * it under the terms of the GNU General Public License as published by # * the Free Software Foundation; either version 2 of the License, or # * (at your option) any later version. # * # * This program is distributed in the hope that it will be useful, # * but WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # * GNU General Public License for more details. # * # * You should have received a copy of the GNU General Public License # * along with this program; if not, write to the Free Software # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # * # * $Id$ # */ """ Framework for accessing user data This class really contains 3 types of functions: 1) private - all of these begin with "__" (2 underscores) 2) public, user related - all of these are public, and have to do something with the user access management 3) public, utilities - all of these are public, however, they do something different that access management, ie. they return md5 digest in HEX """ import av_log import av_debug import av_settings class User: """ Class to hold all user data and more """ noperm = {"eq":0, "eqa":0, "eqh":0, "eql":0, "eqm":0, "eqr":0, # equipment "user":0, "userl":0, # user "work":0, "worka":0, "workh":0, "workl":0, "workm":0, "workr":0,# work "feat":0, "rules":0, "room":0, "secl":0, "sysl":0, "settings":0,# misc "mess":0, "messs":0} # messaging DisAllowedChars = "!@#$%^&*()_+-={}[]:\";'<>?,./|\\~`" def __init__(self): """ Set all variables to their default values does not return anything """ pass def attach(self,conn): self.conn = conn self.db = conn.db self.html = conn.html self.utils = conn.utils self.__SID = self.conn.getparam("sid") self.__UID = -1 self.__USER = "" self.__NAME = "" self.__PASS = "" self.__PERM = self.__class__.noperm self.__TIMEDOUT = 0 self.TEXTBUF = {"loginerror":"", "logincheckerror":""} if (not self.conn.regexp_a0.match(self.__SID)): self.__SID = "" if (self.__SID or self.conn.getparam("login")): self.checklogin() def getSID(self): return self.__SID def setSID(self,newsid): self.__SID = newsid def getUID(self): return self.__UID def getUSER(self): return self.__USER def setUSER(self,newuser): self.__USER = newuser def getNAME(self): return self.__NAME def setNAME(self,name): self.__NAME = name def getPASS(self): return self.__PASS def setPASS(self,newpass): self.__PASS = newpass def getPERM(self,user=-1): """ Get permissions from DB, if user==-1, use current returns dictionary """ if (user==-1): return self.__PERM # ok, look up user dbid = self.db.newid() dbid.execute( """SELECT `priv_eq`, `priv_eqa`, `priv_eqh`, `priv_eql`, `priv_eqm`, `priv_eqr`, `priv_user`, `priv_userl`, `priv_work`, `priv_worka`, `priv_workh`, `priv_workl`, `priv_workm`, `priv_workr`, `priv_feat`, `priv_rules`, `priv_room`, `priv_lsec`, `priv_lsys`, `priv_settings`, `priv_mess`, `priv_messs` FROM `users` WHERE `id`=""" + str(user) + ";") rows = dbid.rowcount() av_debug.BUGON(rows > 1, "Multiple record found") if (rows == 0): # user not logged in return self.__class__.noperm if (rows > 1): # multiple records found return self.__class__.noperm result = dbid.fetchone() tmp__PERM = self.__class__.noperm tmp__PERM["eq"] = result[0] tmp__PERM["eqa"] = result[1] tmp__PERM["eqh"] = result[2] tmp__PERM["eql"] = result[3] tmp__PERM["eqm"] = result[4] tmp__PERM["eqr"] = result[5] tmp__PERM["user"] = result[6] tmp__PERM["userl"] = result[7] tmp__PERM["work"] = result[8] tmp__PERM["worka"] = result[9] tmp__PERM["workh"] = result[10] tmp__PERM["workl"] = result[11] tmp__PERM["workm"] = result[12] tmp__PERM["workr"] = result[13] tmp__PERM["feat"] = result[14] tmp__PERM["rules"] = result[15] tmp__PERM["room"] = result[16] tmp__PERM["secl"] = result[17] tmp__PERM["sysl"] = result[18] tmp__PERM["settings"] = result[19] tmp__PERM["mess"] = result[20] tmp__PERM["messs"] = result[21] return tmp__PERM def setPERM(self,newperm): self.__PERM = newperm def loadPERM(self): """ Get permissions from DB if login succeeds, 0 is returned, if the user does not exist, 1 is returned, if multiple instances of the user are found (internal error), 2 is returned returns integer """ dbid = self.db.newid() dbid.execute( """SELECT `priv_eq`, `priv_eqa`, `priv_eqh`, `priv_eql`, `priv_eqm`, `priv_eqr`, `priv_user`, `priv_userl`, `priv_work`, `priv_worka`, `priv_workh`, `priv_workl`, `priv_workm`, `priv_workr`, `priv_feat`, `priv_rules`, `priv_room`, `priv_lsec`, `priv_lsys`, `priv_settings`, `priv_mess`, `priv_messs` FROM `users` WHERE `id`=""" + str(self.__UID) + ";") rows = dbid.rowcount() av_debug.BUGON(rows > 1, "Multiple record found") if (rows == 0): # user not logged in return self.__class__.noperm if (rows > 1): # multiple records found return self.__class__.noperm result = dbid.fetchone() self.__PERM["eq"] = result[0] self.__PERM["eqa"] = result[1] self.__PERM["eqh"] = result[2] self.__PERM["eql"] = result[3] self.__PERM["eqm"] = result[4] self.__PERM["eqr"] = result[5] self.__PERM["user"] = result[6] self.__PERM["userl"] = result[7] self.__PERM["work"] = result[8] self.__PERM["worka"] = result[9] self.__PERM["workh"] = result[10] self.__PERM["workl"] = result[11] self.__PERM["workm"] = result[12] self.__PERM["workr"] = result[13] self.__PERM["feat"] = result[14] self.__PERM["rules"] = result[15] self.__PERM["room"] = result[16] self.__PERM["secl"] = result[17] self.__PERM["sysl"] = result[18] self.__PERM["settings"] = result[19] self.__PERM["mess"] = result[20] self.__PERM["messs"] = result[21] return 0 def isloggedin(self): if (self.__SID.__len__()>0): return 1 return 0 def timedout(self): if (self.__TIMEDOUT): return 1 return 0 def checklogin(self): """ Check that the user is logged in, and adjust any variables as needed if login succeeds, "" is returned, if not, HTML string is returned returns string """ if (self.conn.getparam("login")=="yes" and self.__SID): self.TEXTBUF["loginerror"] = "<br /><br /><div class=\"error\">Sorry, fatal error has occured</div>" return if (self.conn.getparam("login")=="yes"): if ((not self.conn.validatestring(self.conn.getparam("user"))) or (not self.conn.validatestring(self.conn.getparam("pass")))): self.TEXTBUF["loginerror"] = "<br /><br /><div class=\"error\">Sorry, username/password contains invalid characters</div>" return if ((not self.conn.getparam("user")) or (not self.conn.getparam("pass"))): self.TEXTBUF["loginerror"] = "<br /><br /><div class=\"error\">Sorry, both username and password are required</div>" return self.TEXTBUF["loginerror"] = self.__login() if (self.TEXTBUF["loginerror"]): return dbid = self.db.newid() dbid.execute("SELECT `id`, `ip`, `user`, `lastac` FROM `online` WHERE `uhash`=\"" + str(self.__SID) + "\";") rowcount = dbid.rowcount() if (rowcount == 0): # user not logged in av_log.syslog(self.conn,"Fatal Error: no records found in online") self.__SID = "" self.TEXTBUF["logincheckerror"] = "<br /><br />You do not appear to be logged in. To log in, select the appropreate option from the menu." return if (rowcount > 1): # multiple records found av_log.syslog(self.conn,"Fatal Error: mutiple records found in online") dbid.execute("DELETE FROM `online` WHERE `uhash`=\"" + self.__SID + "\";") self.__SID = "" self.TEXTBUF["logincheckerror"] = "<br /><br /><div class=\"error\">Error unexpected error occured.</div>You do not appear to be logged in. To log in, select the appropreate option from the menu." return result = dbid.fetchone() if ((result[3]+int(av_settings.getSetting(self.conn,"timeout"))*60)<self.conn.now()): # timed out dbid.execute("DELETE FROM `online` WHERE `id`=" + str(result[0]) + ";") self.__SID = "" self.__PERM = self.__class__.noperm self.__TIMEDOUT = 1 av_log.syslog(self.conn,"User \"" + self.UID2User(result[2]) + "\"'s (UID = " + str(result[2]) + ") session timed out") return # We do not need to set HTML here, the timeout HTML is a LARGE piece of code, that appears in menu() in av_html.py if (result[1]!=self.conn.getIP()): # highjacking attempt occured dbid.execute("DELETE FROM `online` WHERE `id`=" + str(result[0]) + ";") self.__SID = "" self.__PERM = self.__class__.noperm av_log.syslog(self.conn,"User \"" + self.UID2User(result[2]) + "\"'s (UID = " + str(result[2]) + ") session highjacking attempt occured\nLogging user out") self.TEXTBUF["logincheckerror"] = "<br /><br /><div class=\"error\">Error, somebody tried to "highjack" your connection</div>You have been logged out to prevent the attaker from gaining more information." return self.__UID = result[2] self.loadPERM() self.updatelastac() self.kickoldusers() def checkpass(self,pwd): """ Checks user's password against pwd returns bool """ self.__loadUID() dbid = self.db.newid() dbid.execute("SELECT `pass` FROM `users` WHERE `id`=" + str(self.__UID) + ";") if (dbid.rowcount()): # FIXME: what if more than one record is found result = dbid.fetchone() if (self.utils.md5sum(pwd)==result[0]): return 1 return 0 def UID2User(self,uid=-1): """ Find username for user id: uid if uid==-1, use current user returns string """ if (uid==-1): self.__loadUID() uid = self.__UID dbid = self.db.newid() dbid.execute("SELECT `name` FROM `users` WHERE `id`=" + str(uid) + ";") if (dbid.rowcount()): # FIXME: what if multiple recors were returned return dbid.fetchone()[0] return "?" def UID2Name(self,uid=-1): """ Find real user's name for user id: uid if uid==-1, use current user returns string """ if (uid==-1): self.__loadUID() uid = self.__UID dbid = self.db.newid() dbid.execute("SELECT `realname` FROM `users` WHERE `id`=" + str(uid) + ";") if (dbid.rowcount()): # FIXME: what if multiple recors were returned return dbid.fetchone()[0] return "?" def __loadUID(self): """ Retrieve UID from DB does not return anything """ dbid = self.db.newid() dbid.execute("SELECT `user` FROM `online` WHERE `uhash`=\"" + self.__SID + "\";") if (dbid.rowcount()): # FIXME: what if more than one record is returned result = dbid.fetchone() self.__UID = result[0] def changepass(self,npass): """ Change user's password to npass returns bool """ self.__loadUID() dbid = self.db.newid() dbid.execute("UPDATE `users` SET `pass`=\"" + self.utils.md5sum(npass) + "\" WHERE `id`=" + str(self.__UID) + ";") if (dbid.rowcount()): av_log.syslog(self.conn,"User \"" + self.UID2User() + "\" (UID = " + str(self.__UID) + ") changed his password") return 1 return 0 def kickoldusers(self): """ Delete all users that are inactive for more that hardtimeout does not return anything """ dbid = self.db.newid() dbid.execute("SELECT `id`, `user`, `ip` FROM `online` WHERE `lastac`<" + str((self.conn.now()-(int(av_settings.getSetting(self.conn,"hardtimeout"))*60)))) for rec in dbid.fetchall(): av_log.syslog(self.conn,"User \"" + self.UID2User(rec[1]) + "\" (UID = " + str(rec[1]) + ") reached the hardtimeout") dbid.execute("DELETE FROM `online` WHERE `id`=" + str(rec[0]) + ";") def updatelastac(self): """ Update last access time to self.conn.now() does not return anything """ dbid = self.db.newid() dbid.execute("UPDATE `online` SET `lastac`=" + str(self.conn.now()) + " WHERE `uhash`=\"" + self.__SID + "\";") def __login(self): """ Checks user credentials against the database and logs him in is possible if login succeeds, "" is returned, if not, HTML string is returned returns string """ user = self.conn.getparam("user") passwd = self.conn.getparam("pass") md5pass = self.utils.md5sum(passwd) dbid = self.db.newid() dbid.execute( """SELECT `id`, `priv_eq`, `priv_eqa`, `priv_eqh`, `priv_eql`, `priv_eqm`, `priv_eqr`, `priv_user`, `priv_userl`, `priv_work`, `priv_worka`, `priv_workh`, `priv_workl`, `priv_workm`, `priv_workr`, `priv_feat`, `priv_rules`, `priv_room`, `priv_lsec`, `priv_lsys`, `priv_settings`, `priv_mess`, `priv_messs` FROM `users` WHERE `name`='""" + user + "' AND `pass`='" + md5pass + "' AND `active`=1") rowcount = dbid.rowcount() if (rowcount == 0): # user not found av_log.seclog(self.conn,"Failed login with these credintials: user = \"" + user + "\"") return "<br /><br /><div class=\"error\">Sorry, invalid username/password</div>" if (rowcount > 1): # multiple instances found av_log.syslog(self.conn,"Fatal Error: multiple records found in users (user = \"" + user + "\", pass = \"" + md5pass + "\")") return "<br /><br /><div class=\"error\">Sorry, a fatal error occured</div>" result = dbid.fetchone() self.__PERM["eq"] = result[1] self.__PERM["eqa"] = result[2] self.__PERM["eqh"] = result[3] self.__PERM["eql"] = result[4] self.__PERM["eqm"] = result[5] self.__PERM["eqr"] = result[6] self.__PERM["user"] = result[7] self.__PERM["userl"] = result[8] self.__PERM["work"] = result[9] self.__PERM["worka"] = result[10] self.__PERM["workh"] = result[11] self.__PERM["workl"] = result[12] self.__PERM["workm"] = result[13] self.__PERM["workr"] = result[14] self.__PERM["feat"] = result[15] self.__PERM["rules"] = result[16] self.__PERM["room"] = result[17] self.__PERM["secl"] = result[18] self.__PERM["sysl"] = result[19] self.__PERM["settings"] = result[20] self.__PERM["mess"] = result[21] self.__PERM["messs"] = result[22] self.__SID = self.createSID() dbid.execute("INSERT INTO `online` (`id`, `ip`, `user`, `uhash`, `lastac`) VALUES (NULL, '" + self.conn.getIP() + "', " + str(result[0]) + ", '" + self.__SID + "', " + str(self.conn.now()) + ");") # FIXME: need to check that the above works av_log.syslog(self.conn,"User \"" + user + "\" (UID = " + str(result[0]) + ") logged in") return "" def logout(self): """ Log user out does not return anything """ if (not self.isloggedin()): # bail out if used is not logged in av_log.syslog(self.conn,"Someone attempted to log out, without specifying Session ID") return dbid = self.db.newid() dbid.execute("DELETE FROM `online` WHERE `uhash`=\"" + self.__SID + "\";") av_log.syslog(self.conn,"User \"" + self.UID2User() + "\" logged out") self.__SID = "" self.__UID = -1 self.__USER = "" self.__PASS = "" self.__PERM = self.__class__.noperm self.__TIMEDOUT = 0 def createSID(self): """ Creates SID and returns is returns string """ return self.utils.md5sum(self.conn.getIP() + self.conn.getUserAgent() + str(self.conn.now())) if __name__ == "__main__": print "ERROR"