You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-2.1-server/pym/cl_ldap.py

662 lines
23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#-*- coding: utf-8 -*-
#Copyright 2008 Calculate Pack, http://www.calculate-linux.ru
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import re
import popen2
import ldap
import cStringIO
from ldif import LDIFParser
import cl_base
import cl_profile
# Для подсчета символов
import termios, fcntl, struct
class addLdif(LDIFParser):
"""Класс необходимый для добавления записей в LDAP"""
def __init__(self, strInput,ldapCon):
FD = cStringIO.StringIO(strInput)
LDIFParser.__init__(self, FD)
self.ldapCon = ldapCon
def handle(self, dn, entry):
self.ldapCon.add_s(dn, entry.items())
class ldapFunction(cl_profile._error):
'''Объект для работы с LDAP сервером'''
def __init__(self, dnUser, password):
self.conLdap = False
# Получаем соединение с LDAP
try:
self.conLdap = self.__ldapConnect(dnUser, password)
except ldap.LDAPError, e:
self.setError(e[0]['desc'])
def __ldapConnect(self, dnUser, password):
"""Соединение с LDAP сервером"""
conLdap = ldap.initialize('ldap://localhost')
print dnUser, password
conLdap.simple_bind_s(dnUser, password)
return conLdap
def ldapAdd(self, strLdif):
"""Добавляем строку содержащую ldif в LDAP
Если данные существуют - ошибка
"""
if self.conLdap:
try:
# Записываем параметры из ldif файла в LDAP сервер
parser = addLdif(strLdif,self.conLdap)
parser.parse()
except ldap.LDAPError, e:
self.setError(e[0]['desc'])
return False
return True
else:
self.setError(_("No connect to LDAP server"))
return False
Version = "calculate-server 0.0.1"
tr = cl_base.lang()
tr.setLanguage(sys.modules[__name__])
class cl_ldap(cl_profile._error):
def getChapterNumber(self,NameChapter):
# Показать номер раздела по его имени
num = 0
for i in self.chapter:
if i[0] == NameChapter:
return num
num += 1
return False
def __init__(self, cmdName):
# ini файл
self.iniFile = "/etc/calculate/calculate.ini"
self.cmdName = cmdName
self.shortOpt = []
#короткие опции командной строки
self.longOpt = []
#длинные опции командной строки
#optEnd = ""
#if "user" in self.cmdName and not "mod" in self.cmdName:
#optEnd = _("user")
#elif "group" in self.cmdName and not "mod" in self.cmdName:
#optEnd = _("group")
servName = ""
if "user" in self.cmdName:
servName = _("user")
elif "group" in self.cmdName:
servName = _("group")
elif "setup" in self.cmdName:
servName = _("service")
self.chapter = [\
# расположение разделов на странице
# имя раздела, видимый или невидимый, кол. "\n" после
# названия раздела, кол. "\n" после раздела
("Copyright",False,0,2),
(_("Usage"),True,0,1),
("Function",False,0,2),
(_("Examples"),True,1,1),
(_("Options"),True,1,1),
(_("Services"),True,1,1),
(_("Informative output"),True,1,0),
]
self.chapterBloc = []
# разделы справки
for i in self.chapter:
self.chapterBloc.append("")
# имена используемых программ и их номера для доступа к переменным
# self.data
self.progName = { 'cl-groupadd':0,
'cl-groupdel':1,
'cl-groupmod':2,
'cl-useradd':3,
'cl-userdel':4,
'cl-usermod':5,
'cl-setup':6,
}
self.data = [\
# Options
{'progAccess':(3,),
'chortOption':"p",
'longOption':"password",
'optVal':"file",
'helpChapter':_("Options"),
'help':_("input user password")
},
# Services
{'helpChapter':_("Services"),
'help':" ldap \t\t\tldap " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" samba \t\tsamba " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" mail \t\t\tmail " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" ftp \t\t\tftp " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" proxy \t\tproxy " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" radius \t\tradius " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" jabber \t\tjabber " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" addressbook \t\taddressbook " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" dhcp \t\t\tdhcp " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" named \t\tnamed " + servName + "\n"
},
{'helpChapter':_("Services"),
'help':" wiki \t\t\twiki " + servName + "\n"
},
# Informative output
{'chortOption':"h",
'longOption':"help",
'helpChapter':_("Informative output"),
'help':_("display this help and exit")
},
{
#'progAccess':(3,),
'helpChapter':"Copyright",
'help':Version
},
# Использование
{
'progAccess':(3,),
'helpChapter':_("Usage"),
'help': self.cmdName + " " + " [" + _("options") + "] " + _("user") +\
" " + _("service")
},
{
'progAccess':(6,),
'helpChapter':_("Usage"),
'help': self.cmdName + " " + " [" + _("options") + "] "+\
" " + _("service")
},
{
'progAccess':(0,),
'helpChapter':"Function",
'help':_("Adds group in LDAP directory of service")
},
{
'progAccess':(1,),
'helpChapter':"Function",
'help':_("Deletes group from LDAP of directory of service")
},
{
'progAccess':(2,),
'helpChapter':"Function",
'help':_("Modifies group profiles from LDAP of directory of service")
},
{
'progAccess':(3,),
'helpChapter':"Function",
'help':_("Adds user in LDAP directory of service")
},
{
'progAccess':(4,),
'helpChapter':"Function",
'help':_("Deletes user from LDAP of directory of service")
},
{
'progAccess':(5,),
'helpChapter':"Function",
'help':_("Modifies user profiles from LDAP of directory of service")
},
{
'progAccess':(6,),
'helpChapter':"Function",
'help':_("Sets service in the system")
},
# Примеры
{
'progAccess':(0,),
'helpChapter':_("Examples"),
'help':" " + _("cl-groupadd -smfw guest\t # add group guest \
in services:\n\
\t\t\t\t # samba, mail, ftp, wiki.")
},
{
'progAccess':(1,),
'helpChapter':_("Examples"),
'help':" " + _("cl-groupdel -smfw guest\t # delete group \
guest in services:\n\
\t\t\t\t # samba, mail, ftp, wiki.""")
},
{
'progAccess':(2,),
'helpChapter':_("Examples"),
'help':""
},
{
'progAccess':(3,),
'helpChapter':_("Examples"),
'help':" " + "cl-useradd guest samba #" +_("add user guest in \
service samba") + ".\n"
},
{
'progAccess':(4,),
'helpChapter':_("Examples"),
'help': " " + _("cl-userdel -smfw guest\t # delete user \
guest in services:\n\
\t\t\t\t # samba, mail, ftp, wiki.""")
},
{
'progAccess':(5,),
'helpChapter':_("Examples"),
'help':""
},
{
'progAccess':(6,),
'helpChapter':_("Examples"),
'help':" " + "cl-setup samba #"+_("set service") + " samba " +\
_("in the system") + ".\n"
},
]
self.__setParamHelp()
#Название всех сервисов
self.allServ = []
self.__setAllServ()
def __setAllServ(self):
"""Записывает в аттрибут self.allServ названия всех сервисов"""
sServ = re.compile("\s*([^\s]+)\s*")
for par in self.data:
if par.has_key('helpChapter') and\
par['helpChapter'] == _("Services") and\
par.has_key('help'):
res = sServ.search(par['help'])
if res:
self.allServ.append(res.group(1))
def addChapterHelp(self,numChapter,helpTxt):
# Добавить в раздел помощи numChapteк тектстовую строку helpTxt
self.chapterBloc[numChapter] += helpTxt
return True
def addData(self,dataHash):
# На будущее (добавляет опции)
self.data.append(dataHash)
return True
def access(self,dataHash):
# доступна ли опция вызывающей программе
numProg = self.progName[self.cmdName]
if dataHash.has_key('progAccess'):
if numProg in dataHash['progAccess']:
return True
else:
return False
else:
return True
def __setParamHelp(self):
# записать параметры в справку
sp = []
for par in self.data:
if par.has_key("chortOption"):
if self.access(par):
sp.append(par["chortOption"])
sp.sort()
for shortOption in sp:
for par in self.data:
if par.has_key("chortOption"):
if par["chortOption"] == shortOption:
tab = "\t\t"
if par.has_key("optVal"):
longOption = par["longOption"] + "=" +\
par["optVal"]
else:
longOption = par["longOption"]
if len(longOption) >= 8:
tab = "\t"
elif len(longOption) >= 16:
tab = ""
numChapter = self.getChapterNumber(par['helpChapter'])
helpTxt = " -" + par["chortOption"] + ", --" +\
longOption + tab + par['help'] + "\n"
self.addChapterHelp(numChapter,helpTxt)
break
for par in self.data:
if not par.has_key("chortOption") and \
self.access(par):
helpTxt = par['help']
numChapter = self.getChapterNumber(par['helpChapter'])
self.addChapterHelp(numChapter,helpTxt)
def getHelp(self):
# Выдать справку
help = ""
for numChapter in range(len(self.chapter)):
chapter = self.chapter[numChapter]
nameChapter = chapter[0]
visibleChapter = chapter[1]
beforeStrChapter = chapter[2]
afterStrChapter = chapter[3]
bef = ""
for i in range(beforeStrChapter):
bef += "\n"
aft = ""
for i in range(afterStrChapter):
aft += "\n"
if visibleChapter:
help += nameChapter + ": " + bef
help += self.chapterBloc[numChapter] + aft
return help
def getAllOpt(self,typeOpt="short"):
# Выдать все действующие опции
if typeOpt=="short":
if len(self.shortOpt) == 0:
for par in self.data:
if par.has_key("chortOption") and self.access(par):
if par.has_key("optVal"):
self.shortOpt.append(par["chortOption"]+':')
else:
self.shortOpt.append(par["chortOption"])
return "".join(self.shortOpt)
if typeOpt=="long":
if len(self.longOpt) == 0:
for par in self.data:
if par.has_key("longOption") and self.access(par):
if par.has_key("optVal"):
self.longOpt.append(par["longOption"]+'=')
else:
self.longOpt.append(par["longOption"])
return self.longOpt
def getShortOpt(self,option):
# Из любой опции получаем короткую опцию
for par in self.data:
if par.has_key("chortOption") and self.access(par):
if par["longOption"] == option or \
par["chortOption"] == option:
return par["chortOption"]
break
return ""
def getRunService(self, nameService):
"""Проверка, запущен ли сервис с данным именем"""
baseDir = "/var/run"
addDirDict = {"ldap":"openldap",}
pidDir = baseDir + "/" + addDirDict[nameService]
if os.access(pidDir, os.F_OK) and os.listdir(pidDir):
return True
else:
return False
def getParamIniFile(self, name):
"""Получаем значение параметра по его имени из ini файла"""
if os.access(self.iniFile, os.F_OK):
FD = open (self.iniFile)
lines = FD.read().splitlines()
FD.close()
dictParam = {}
for par in lines:
n ,v = par.split("=")
if not dictParam.has_key(n.strip()):
dictParam[n.strip()] = v.strip()
if dictParam.has_key(name):
return dictParam[name]
else:
return ""
else:
self.setError(_("Not found ini file:")) + "\n " + self.iniFile
return False
def setParamIniFile(self, name, value):
"""Записываем новый параметр в ini файл"""
if os.access(self.iniFile, os.F_OK):
FD = open (self.iniFile)
lines = FD.read().splitlines()
FD.close()
dictParam = {}
newLines = []
for par in lines:
n ,v = par.split("=")
if not dictParam.has_key(n.strip()):
dictParam[n.strip()] = v.strip()
newLines.append((n.strip(),v.strip(),par))
if dictParam.has_key(name):
i = 0
for n,v,l in newLines:
if n == name:
newLines[i] = (name, value, name + "=" + value)
break
i += 1
else:
newLines.append((name, value, name + "=" + value))
if newLines:
FD = open (self.iniFile, "w")
FD.truncate(0)
FD.seek(0)
for n,v,l in newLines[:-1]:
FD.write(l+"\n")
FD.write(newLines[-1][2])
FD.close()
return True
else:
self.setError(_("Not found ini file:")) + "\n " + self.iniFile
return False
def delParamIniFile(self, name):
"""Удаляет параметр из ini файла"""
if os.access(self.iniFile, os.F_OK):
FD = open (self.iniFile)
lines = FD.read().splitlines()
FD.close()
dictParam = {}
newLines = []
for par in lines:
n ,v = par.split("=")
if not dictParam.has_key(n.strip()):
dictParam[n.strip()] = v.strip()
if n.strip() != name:
newLines.append((n.strip(),v.strip(),par))
FD = open (self.iniFile, "w")
FD.truncate(0)
FD.seek(0)
if newLines:
for n,v,l in newLines[:-1]:
FD.write(l+"\n")
FD.write(newLines[-1][2])
else:
FD.write("")
FD.close()
return True
else:
self.setError(_("Not found ini file:")) + "\n " + self.iniFile
return False
def createLdif(self, ldifFile, objVars):
"""Cоздает ldif из ldif - профиля"""
if not os.access(ldifFile, os.F_OK):
self.setError(_("Not found file:")) + "\n " + ldifFile
return False
FD = open (ldifFile)
ldifProfile = FD.read()
FD.close()
clProf = cl_profile.profile(objVars)
# Применяем условия к профилю
ldifProfile = clProf.applyTermsProfile(ldifProfile,ldifFile)
# Заменяем переменные
ldifProfile = clProf.applyVarsProfile(ldifProfile)
return ldifProfile
def execProg(self, cmdStrProg):
"""Выполняет внешнюю программу
результат строка которую выведет внешняя программа
"""
fout, fin = popen2.popen2(cmdStrProg)
fin.close()
textLine = fout.readline()
fout.close()
return textLine
def printRight(self, right):
"""Переводит курсор на позицию right справа от края консоли
"""
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
#(rows, cols, x pixels, y pixels)
cols = struct.unpack("HHHH", x)[1]
for i in range(cols-right):
sys.stdout.write(" ")
def colorPrint(self,attr,fg,bg,string):
"""Раскрашивает выводимое сообщение
Параметры:
attr - это атрибут
fg - цвет символа
bg - цвет фона
в случае если параметр равен "" то он не изменяется
attr может принимать следующие значения:
0 сбросить все атрибуты (вернуться в нормальный режим)
1 яркий (обычно включает толстый шрифт)
2 тусклый
3 подчёркнутый
5 мигающий
7 реверсный
8 невидимый
fg может принимать следующие значения:
30 чёрный
31 красный
32 зелёный
33 жёлтый
34 синий
35 фиолетовый
36 голубой
37 белый
bg может принимать следующие значения:
40 чёрный
41 красный
42 зелёный
43 жёлтый
44 синий
45 фиолетовый
46 голубой
47 белый
"""
lst = []
if attr:
lst.append(attr)
if fg:
lst.append(fg)
if bg:
lst.append(bg)
sys.stdout.write("\033[%sm%s\033[0m" %(";".join(lst),string))
def greenPrint(self, string):
"""Печатает зеленое сообщение"""
self.colorPrint("1","32","",string)
def bluePrint(self, string):
"""Печатает фиолетовое сообщение"""
self.colorPrint("1","34","",string)
def setupLdapServer(self):
"""Начальная настройка Ldap сервиса"""
# Проверим запущен ли ldap
if self.getRunService("ldap"):
print _("The LDAP service is running")
print "1. " +_("Stop the LDAP service")
print " /etc/init.d/slapd stop"
print "2. " + _("You can save configuration files and a database \
LDAP in backup directory")
print "3. " + _("Restart the program")
return True
clVars = cl_base.DataVars()
clVars.flServer()
# Для тестовых целей устанавливаем директорию инсталяции
clVars.Set("setup_path_install","/tmp/test1/")
# Устанавливаем переменную (говорит о том что первый проход)
clVars.Set("setup_pass_parser","1",True)
# Cоздаем объект профиль устанавливая директорию ldap для
# файлов профилей
clProf = cl_profile.profile(clVars,"ldap")
# Объединяем профили
clProf.applyProfiles()
# Удаляем предыдущую базу данных
print _("Remove previons Ldap Database ...")
self.execProg("rm -rf /var/lib/openldap-data/*")
# Запускаем LDAP сервер
textLine = self.execProg("/etc/init.d/slapd start")
ldifFile = "/usr/lib/calculate/calculate-server/ldif/ldap_base.ldif"
self.printRight(6)
self.bluePrint("[")
self.greenPrint(" ok ")
self.bluePrint("]")
print
if "ok" in textLine:
print "LDAP start OK"
else:
print "Error Ldap start"
return False
baseLdif = self.createLdif(ldifFile, clVars)
#print baseLdif
print clVars.Get("soft_ldap_root_tmp")
rootTmpDn = clVars.Get("soft_ldap_root_tmp")
#print clVars.Get("soft_ldap_rootpw_tmp")
#print clVars.Get("soft_ldap_rootpw_tmp_hash")
print clVars.Get("soft_ldap_rootpw_tmp")
#clVars.printVars()
ldapObj = ldapFunction(clVars.Get("soft_ldap_root_tmp"),
clVars.Get("soft_ldap_rootpw_tmp"))
if not ldapObj.getError():
ldapObj.ldapAdd(baseLdif)
if ldapObj.getError():
print _("LDAP Error") + ": " + ldapObj.getError()
#self.setParamIniFile("test","param")
#self.setParamIniFile("test1","param1")
#self.delParamIniFile("test1")
#self.delParamIniFile("test")
#print self.getParamIniFile("test")