From a7edeca826e8a6e0d5ef5dcae4c7dab5c91de731 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sat, 25 Dec 2004 23:09:19 +0000 Subject: [PATCH] - added gnuviech package - better code structure - class for domain - class for preferences - password generation function git-svn-id: file:///home/www/usr01/svn/gnuviechadmin/gnuviech.info/gnuviechadmin/trunk@82 a67ec6bc-e5d5-0310-a910-815c51eb3124 --- backend/GNVAdm.py | 101 ++++++++++++++++++++++++++++++ backend/GVAdm.py | 37 ----------- backend/gnuviech/__init__.py | 67 ++++++++++++++++++++ backend/gnuviech/tools.py | 20 ++++++ backend/gvadm.preferences.default | 10 --- backend/gvadm.py | 2 - backend/mailtools.py | 52 +++++++-------- backend/test.py | 20 ++++++ 8 files changed, 235 insertions(+), 74 deletions(-) create mode 100644 backend/GNVAdm.py delete mode 100644 backend/GVAdm.py create mode 100644 backend/gnuviech/__init__.py create mode 100644 backend/gnuviech/tools.py delete mode 100644 backend/gvadm.preferences.default delete mode 100644 backend/gvadm.py create mode 100644 backend/test.py diff --git a/backend/GNVAdm.py b/backend/GNVAdm.py new file mode 100644 index 0000000..bc13a96 --- /dev/null +++ b/backend/GNVAdm.py @@ -0,0 +1,101 @@ +"""Package for GNUViech Admin main types and functions + +(c) Copyright 2004 Jan Dittberner, IT-Consulting & Solutions + Germany +""" + +import os +import gnuviech + +class DomainNotExistentError(Exception): pass + +class DomainFileNotExistentError(Exception): pass + +class GNVDomain: + """Represents a domain in the GNUViech admin tool""" + + def __init__(self, domain): + """Initializes the domain object""" + self.name = domain + try: + self.findUser() + except gnuviech.NoAdmDirError: + gnuviech.setupDirs() + self.__init__(domain) + except DomainFileNotExistentError: + self.createDomainFile() + self.__init__(domain) + except DomainNotExistentError: + self.createUser() + + def __repr__(self): + retval = "Domain "+self.name + if not self.username is None: + retval += ", User "+self.username + else: + retval += ", new domain" + return retval + + def createDomainFile(self): + """Create the domain user id map file.""" + file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "w") + file.close() + + def createUser(self): + """Create a user for the domain.""" + file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "r") + id = 0 + for line in file.readlines(): + (key, value) = line.split(":") + if (int(value) > id): id = int(value) + file.close() + id += 1 + file = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "a") + file.write("%s:%d\n" % (self.name, id)) + file.close() + self.findUser() + + def findUser(self): + """Finds the user for the domain.""" + self.username = None + if (os.access(gnuviech.GNVPrefs.GVADMDIR, os.R_OK)): + try: + domainsfile = open(gnuviech.GNVPrefs.GVADMDIR+"domains", "r") + for line in domainsfile.readlines(): + (key, value) = line.split(":") + if (key == self.name): + self.username = "%s%02d" % ( + gnuviech.GNVPrefs.USERPREFIX, + int(value)) + domainsfile.close() + if self.username is None: + raise DomainNotExistentError + except IOError: + raise DomainFileNotExistentError + else: + raise gnuviech.NoAdmDirError + + def getMaxPop3Id(self): + maxid = 0 + try: + passwdfile = open(gnuviech.GNVPrefs.BASEPREFIX+"/etc/passwd", "r") + for line in passwdfile.readlines(): + (login, passwd, uid, gid, name, dir, shell) = line.split(":") + if login.startswith(self.username + "p"): + id = int(login[len(self.username):]) + print id + if (id > maxid): maxid = id + except IOError: + pass + return maxid + + def getNextUser(self, usertype): + """Gets the next user for the given type.""" + if (usertype == "web"): + return self.username + if (usertype == "pop3"): + return "%sp%d" % (self.username, self.getMaxPop3Id()+1) + +if __name__ == "__main__": + dom = GNVDomain("dittberner.info") + print dom diff --git a/backend/GVAdm.py b/backend/GVAdm.py deleted file mode 100644 index 2b7a698..0000000 --- a/backend/GVAdm.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Package for GNUViech Admin main types and functions - -(c) Copyright 2004 Jan Dittberner, IT-Consulting & Solutions - Germany -""" - -import os - -execfile('gvadm.preferences') - -class GNVDomain: - """Represents a domain in the GNUViech admin tool""" - - def __init__(self, domain): - """Initializes the domain object""" - self.domainname = domain - self.findUser() - - def __repr__(self): - return "Domain "+self.domainname+", User "+self.username - - def findUser(self): - """Finds the user for the domain or creates a new one.""" - if (os.access(GVADMDIR, os.R_OK)): - try: - domainsfile = open(GVADMDIR+"domains", "r") - self.username = "" - except IOError: - print "domain file not accessible" - self.username = "" - else: - print "The directory "+GVADMDIR+" is not accessible!" - self.username = "" - -if __name__ == "__main__": - dom = GNVDomain("test.de") - print dom diff --git a/backend/gnuviech/__init__.py b/backend/gnuviech/__init__.py new file mode 100644 index 0000000..d30dffb --- /dev/null +++ b/backend/gnuviech/__init__.py @@ -0,0 +1,67 @@ +"""GNUViech administration tool helper classes. + +(c) 2004 Jan Dittberner +""" + +import os + +class GNVPrefs: + """This class has static variables for the settings of the GNUViech + administration tool. These settings can be customized in the file + gvadm.preferences.""" + # define standard values + PWDMINLENGTH = 6 + PWDMAXLENGTH = 12 + PWDCHARS = range(ord('a'), ord('z')) + PWDCHARS.extend(range(ord('A'), ord('Z'))) + PWDCHARS.extend(range(ord('0'), ord('9'))) + PWDCHARS.extend((ord('@'), ord('#'), ord(','), ord('.'), ord('*'), + ord('+'), ord('-'), ord('='), ord('!'), ord('$'), + ord('"'))) + USERPREFIX = "usr" + BASEPREFIX = "" + GVADMDIR = BASEPREFIX+"/etc/gvadm/" + EXIMCONFDIR = BASEPREFIX+"/etc/exim/" + VIRTUALDOMDIR = EXIMCONFDIR+"virtual/" + HOMEDIR = BASEPREFIX+"/home" + POPHOMEDIR = HOMEDIR+"/mail/" + WEBHOMEDIR = HOMEDIR+"/www/" + WEBLOGDIR = WEBHOMEDIR+"logs/" + WEBSTATSDIR = WEBHOMEDIR+"stats/" + # load custom settings + execfile("gvadm.preferences") + + def __repr__(self): + items = dir(self) + items.sort() + return "gnuviech.GNVPrefs\n\t" + "\n\t".join(["%s = %s" % + (item, getattr(self, item)) for item in items if getattr(self, item).__class__ in (str, int, list, dict)]) + "\n" + +class NoAdmDirError(Exception): + """This exception is raised if the admin directory does'nt exist.""" + pass + +def setupDirs(): + """Setup the directories and files required for proper operation of the + GNUViech administration tool.""" + for directory in (GNVPrefs.BASEPREFIX, + GNVPrefs.BASEPREFIX+"/etc", + GNVPrefs.GVADMDIR, + GNVPrefs.EXIMCONFDIR, + GNVPrefs.VIRTUALDOMDIR, + GNVPrefs.HOMEDIR, + GNVPrefs.POPHOMEDIR, + GNVPrefs.WEBHOMEDIR, + GNVPrefs.WEBLOGDIR, + GNVPrefs.WEBSTATSDIR): + if (not os.access(directory, os.R_OK & os.X_OK)): + print "making %s." % directory + os.mkdir(directory) + for required in (GNVPrefs.BASEPREFIX+"/etc/passwd", + GNVPrefs.BASEPREFIX+"/etc/shadow", + GNVPrefs.EXIMCONFDIR+"eximpasswords"): + if (not os.access(required, os.R_OK)): + print "creating %s." % required + file = open(required, "w") + file.close() + diff --git a/backend/gnuviech/tools.py b/backend/gnuviech/tools.py new file mode 100644 index 0000000..e2c312b --- /dev/null +++ b/backend/gnuviech/tools.py @@ -0,0 +1,20 @@ +"""Tool functions for GNUViech administration tool + +(c) 2004 Jan Dittberner +""" + +from random import Random +from gnuviech import GNVPrefs + +def generatePassword(): + r = Random() + devrnd = open("/dev/random", "r") + r.seed(ord(devrnd.read(1))) + devrnd.close() + return "".join([chr(char) for char in + r.sample(GNVPrefs.PWDCHARS, + r.randint(GNVPrefs.PWDMINLENGTH, + GNVPrefs.PWDMAXLENGTH))]) + +# regex für email check +# p = re.compile(u"^([a-zA-Z0-9_\-.]+)@([a-zA-Z0-9\-]+(\.|[a-zA-Z0-9\-]+)*\.[a-z]{2,5})$") diff --git a/backend/gvadm.preferences.default b/backend/gvadm.preferences.default deleted file mode 100644 index 24c4f50..0000000 --- a/backend/gvadm.preferences.default +++ /dev/null @@ -1,10 +0,0 @@ -USERPREFIX = "usr" -BASEPREFIX = "" -GVADMDIR = BASEPREFIX+"/etc/gvadm/" -EXIMCONFDIR = BASEPREFIX+"/etc/exim/" -VIRTUALDOMDIR = EXIMCONFDIR+"virtual/" -HOMEDIR = BASEPREFIX+"/home" -POPHOMEDIR = HOMEDIR+"/mail/" -WEBHOMEDIR = HOMEDIR+"/www/" -WEBLOGDIR = WEBHOMEDIR+"logs/" -WEBSTATSDIR = WEBHOMEDIR+"stats/" diff --git a/backend/gvadm.py b/backend/gvadm.py deleted file mode 100644 index 36a6acd..0000000 --- a/backend/gvadm.py +++ /dev/null @@ -1,2 +0,0 @@ -import mailtools - diff --git a/backend/mailtools.py b/backend/mailtools.py index e04882c..487156c 100755 --- a/backend/mailtools.py +++ b/backend/mailtools.py @@ -1,10 +1,8 @@ #! /usr/bin/env python import os, string -import GVAdm -from UserDict import UserDict - -execfile('gvadm.preferences') +import gnuviech +from GNVAdm import GNVDomain # if [ -n $USERPREFIX ]; then # USERPREFIX="usr" @@ -29,11 +27,15 @@ execfile('gvadm.preferences') # echo "Herzlich willkommen auf dem GNU-Viech" | mail -s "Willkommen auf dem GNU-Viech" ${NEWUSER} # echo added new pop3 user $NEWUSER with password $NEWPASS -class MailAccount(UserDict): +class MailAccount: def __init__(self, domain): "Initialize a MailAccount instance for a given domain" - UserDict.__init__(self) - self["domainname"] = domain + if (not os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK & os.X_OK)): + self.setupDirs() + self.domain = domain + + def setupDirs(self): + os.mkdir(gnuviech.GNVPrefs.VIRTUALDOMDIR) class MailAlias(MailAccount): """This represents a mail alias""" @@ -41,46 +43,46 @@ class MailAlias(MailAccount): def __init__(self, domain): "Initialize the POPAccount class for a given domain" MailAccount.__init__(self, domain) - self["aliases"] = {} + self.aliases = {} self.readAll() def readAll(self): """reads the aliasfile for the given domain""" - self["aliases"] = {} - if (os.access(VIRTUALDOMDIR, os.R_OK)): + self.aliases = {} + if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.R_OK)): try: - aliasfile = open(VIRTUALDOMDIR+self["domainname"], 'r') + aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name , 'r') for line in aliasfile.readlines(): keyvals = string.split(line,":",1) - self["aliases"][keyvals[0]] = keyvals[1].strip() + self.aliases[keyvals[0]] = keyvals[1].strip() aliasfile.close() except IOError: - print "couldn't read the aliasfile for "+self["domainname"]+"." + print "couldn't read the aliasfile for "+self.domain.name+"." else: - print "couldn't read from "+VIRTUALDOMDIR+"." + print "couldn't read from "+gnuviech.GNVPrefs.VIRTUALDOMDIR+"." def writeAll(self): """writes the aliasfile for the given domain with the aliases defined in the dictionary object aliases""" - if (os.access(VIRTUALDOMDIR, os.W_OK)): + if (os.access(gnuviech.GNVPrefs.VIRTUALDOMDIR, os.W_OK)): try: - aliasfile = open(VIRTUALDOMDIR+self["domainname"], 'w') - keys = self["aliases"].keys(); + aliasfile = open(gnuviech.GNVPrefs.VIRTUALDOMDIR+self.domain.name, 'w') + keys = self.aliases.keys(); keys.sort(); for key in keys: - aliasfile.write(key+":"+self["aliases"][key]+"\n") + aliasfile.write("%s:%s" % (key, self.aliases[key]) + "\n") aliasfile.close() except IOError: print "writing to aliasfile failed." else: - print "no write access to directory "+VIRTUALDOMDIR+"." + print "no write access to directory "+gnuviech.GNVPrefs.VIRTUALDOMDIR+"." def setAlias(self, alias, target): """sets a mail alias for given domain which directs the MTA to the given target """ self.readAll() - self["aliases"][alias]=target + self.aliases[alias]=target self.writeAll() class POP3Account(MailAccount): @@ -90,16 +92,16 @@ class POP3Account(MailAccount): """Creates a pop3/imap account for the domain""" print self print "adding address "+address - alias = MailAlias(self["domainname"]) - alias.setAlias(address, "usr03") + alias = MailAlias(self.domain) + alias.setAlias(address, self.domain.getNextUser("pop3")) print alias if __name__ == "__main__": - popacc = POP3Account("test.de") + popacc = POP3Account(GNVDomain("dittberner.info")) print popacc - popacc.create("webmaster") + popacc.create("test") - alias = MailAlias("test.de") + alias = MailAlias(GNVDomain("dittberner.info")) print alias alias.setAlias("klaus", "klaus@dittberner.info") print alias diff --git a/backend/test.py b/backend/test.py new file mode 100644 index 0000000..d7af80a --- /dev/null +++ b/backend/test.py @@ -0,0 +1,20 @@ +import gnuviech +import gnuviech.tools + +if __name__ == "__main__": + print gnuviech.GNVPrefs() + minlen = 0 + avglen = 0 + maxlen = 0 + pwds = 20 + for i in range(pwds): + pwd = gnuviech.tools.generatePassword() + print "%02d: %s (%d)" % (i, pwd, len(pwd)) + if (minlen == 0) or (len(pwd) < minlen): minlen = len(pwd) + if (len(pwd) > maxlen): maxlen = len(pwd) + avglen += len(pwd) + avglen = avglen/pwds + print """average password length: %d +minimum password length: %d +maximum password length: %d""" % (avglen, minlen, maxlen) +