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.2-install/pym/cl_migrate_users.py

399 lines
16 KiB

#-*- coding: utf-8 -*-
# Copyright 2010 Mir Calculate Ltd. http://www.calculate-linux.org
#
# 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, sys, re, time
from cl_utils import pathJoin
from cl_print import color_print
from encrypt import encrypt
from cl_lang import lang
lang().setLanguage(sys.modules[__name__])
class _shareData:
"""Share class"""
_reNumb = re.compile("^\d+$")
def getDataInFile(self, fileName='', lenData=7):
"""Get data list from file"""
return filter(lambda x: len(x)==lenData,
map(lambda x: x.rstrip().split(":"), open(fileName)))
class migrateGroups(_shareData):
"""Migrate group to new system"""
maxGid = 65000
minGid = 500
fileGroups = "/etc/group"
def __init__(self, prefixNewSystem):
self.prefixNewSystem = prefixNewSystem
def getData(self, fileName=''):
if not fileName:
fileName = self.fileGroups
return self.getDataInFile(fileName=fileName, lenData=4)
def getThisData(self):
"""Get data migrate groups in this system"""
return filter(lambda x:\
self._reNumb.match(x[2]) and self.minGid<=int(x[2])<=self.maxGid, self.getData())
def getNewData(self):
"""Get data migrate groups in new system"""
fileName = pathJoin(self.prefixNewSystem, self.fileGroups)
return filter(lambda x:\
self._reNumb.match(x[2]) and self.minGid<=int(x[2])<=self.maxGid, self.getData(fileName=fileName))
def getNewDataSystemGroups(self):
"""Get data system groups in new system"""
fileName = pathJoin(self.prefixNewSystem, self.fileGroups)
return filter(lambda x:\
self._reNumb.match(x[2]) and int(x[2])<self.minGid, self.getData(fileName=fileName))
def getNewProcessedData(self):
"""Get processed data migrate groups in new system"""
# data this Group no users
dataThisGroupsNoUsers = map(lambda x: x[:3]+[""], self.getThisData())
dataNewGroups = self.getNewData()
namesNewGroups = map(lambda x: x[0], dataNewGroups)
gidsNewGroups = map(lambda x: x[2], dataNewGroups)
for data in dataThisGroupsNoUsers:
nameGroup = data[0]
gid = data[2]
if nameGroup in namesNewGroups:
dataNewGroups = filter(lambda x: x[0]!=nameGroup,dataNewGroups)
namesNewGroups = map(lambda x: x[0], dataNewGroups)
gidsNewGroups = map(lambda x: x[2], dataNewGroups)
if gid in gidsNewGroups:
dataNewGroups = filter(lambda x: x[2]!=gid, dataNewGroups)
namesNewGroups = map(lambda x: x[0], dataNewGroups)
gidsNewGroups = map(lambda x: x[2], dataNewGroups)
systemGroupsNewData = self.getNewDataSystemGroups()
return systemGroupsNewData, dataNewGroups, dataThisGroupsNoUsers
class migrateUsers(_shareData):
"""Migrate users to new system"""
maxId = 65000
minId = 500
filePasswd = "/etc/passwd"
def __init__(self, prefixNewSystem):
self.prefixNewSystem = prefixNewSystem
def getData(self, fileName=''):
if not fileName:
fileName = self.filePasswd
return self.getDataInFile(fileName=fileName, lenData=7)
def getThisData(self):
"""Get data migrate users in this system"""
return filter(lambda x:\
self._reNumb.match(x[2]) and self.minId<=int(x[2])<=self.maxId, self.getData())
def getNewData(self):
"""Get data migrate users in new system"""
fileName = pathJoin(self.prefixNewSystem, self.filePasswd)
return filter(lambda x:\
self._reNumb.match(x[2]) and self.minId<=int(x[2])<=self.maxId, self.getData(fileName=fileName))
def getNewDataSystemUsers(self):
"""Get data system users in new system"""
fileName = pathJoin(self.prefixNewSystem, self.filePasswd)
return filter(lambda x:\
self._reNumb.match(x[2]) and int(x[2])<self.minId, self.getData(fileName=fileName))
def getNewProcessedData(self):
"""Get processed data migrate groups in new system"""
# data this Group no users
dataThisUsers = self.getThisData()
dataNewUsers = self.getNewData()
namesNewUsers = map(lambda x: x[0], dataNewUsers)
uidsNewUsers = map(lambda x: x[2], dataNewUsers)
for data in dataThisUsers:
nameUser = data[0]
uid = data[2]
if nameUser in namesNewUsers:
dataNewUsers = filter(lambda x: x[0]!=nameUser, dataNewUsers)
namesNewUsers = map(lambda x: x[0], dataNewUsers)
uidsNewUsers = map(lambda x: x[2], dataNewUsers)
if uid in uidsNewUsers:
dataNewUsers = filter(lambda x: x[2]!=uid, dataNewUsers)
namesNewUsers = map(lambda x: x[0], dataNewUsers)
uidsNewUsers = map(lambda x: x[2], dataNewUsers)
systemUsersNewData = self.getNewDataSystemUsers()
return systemUsersNewData, dataNewUsers, dataThisUsers
class migrateShadow(_shareData):
"""Migrate users to new system"""
fileShadow = "/etc/shadow"
def __init__(self, sysNewMigrateUsers, newMigrateUsers, thisMigrateUsers,
prefixNewSystem):
self.prefixNewSystem = prefixNewSystem
self.sysNewMigrateUsers = sysNewMigrateUsers
self.newMigrateUsers = newMigrateUsers
self.thisMigrateUsers = thisMigrateUsers
def getData(self, fileName=''):
if not fileName:
fileName = self.fileShadow
return self.getDataInFile(fileName=fileName, lenData=9)
def getThisData(self):
"""Get data migrate users in this system"""
return filter(lambda x: x[0] in self.thisMigrateUsers, self.getData())
def getNewData(self):
"""Get data migrate users in new system"""
fileName = pathJoin(self.prefixNewSystem, self.fileShadow)
return filter(lambda x: x[0] in self.newMigrateUsers,
self.getData(fileName=fileName))
def getNewDataSystemShadow(self):
"""Get data system users in new system"""
fileName = pathJoin(self.prefixNewSystem, self.fileShadow)
return filter(lambda x: x[0] in self.sysNewMigrateUsers,
self.getData(fileName=fileName))
def getNewProcessedData(self):
"""Get processed data migrate groups in new system"""
# data this Group no users
dataThisShadow = self.getThisData()
dataNewShadow = self.getNewData()
namesNewShadow = map(lambda x: x[0], dataNewShadow)
for data in dataThisShadow:
nameUser = data[0]
if nameUser in namesNewShadow:
dataNewShadow = filter(lambda x: x[0]!=nameUser, dataNewShadow)
systemShadowNewData = self.getNewDataSystemShadow()
return systemShadowNewData, dataNewShadow, dataThisShadow
class migrate(color_print):
"""Migrate users ang groups to new system"""
templateShadow = "%(user)s:%(hash)s:%(days)s:0:%(maxDays)s:%(warnDays)s:::"
templateUser="%(user)s:x:%(id)s:%(gid)s::/home/%(user)s:/bin/bash"
templateGroup="%(group)s:x:%(gid)s:"
dataUsers = []
dataGroups = []
dataShadow = []
maxId = 65000
minId = 1000
maxGid = 65000
minGid = 1000
minSysId = 500
newUserGroups = ["audio", "cdrom", "plugdev", "video", "wheel", "users"]
def __init__(self, prefixNewSystem):
self.prefixNewSystem = prefixNewSystem
self.objGroups = migrateGroups(self.prefixNewSystem)
self.objUsers = migrateUsers(self.prefixNewSystem)
def addThisUsersToGroups(self, users):
"""Add users to groups"""
thisGroupsData = self.objGroups.getData()
thisGroupsData = map(lambda x: (x[0],x[3].split(',')),
thisGroupsData)
dataGroups = []
for data in self.dataGroups:
groupName = data[0]
thisUsersInGroup = map(lambda x: x[1],
filter(lambda x: x[0]==groupName, thisGroupsData))
thisUsersInGroup = reduce(lambda x,y: x+y, thisUsersInGroup,[])
addUsers = list(set(thisUsersInGroup)&set(users))
if addUsers:
newUsersInGroup = data[3].split(',')
for user in addUsers:
if not user in newUsersInGroup:
newUsersInGroup.append(user)
data[3] = ','.join(newUsersInGroup)
dataGroups.append(data)
self.dataGroups = dataGroups
return self.dataGroups
def getNextUid(self):
"""get next uid"""
listUid = map(lambda x: int(x[2]),
filter(lambda x:\
self.objUsers._reNumb.match(x[2]) and\
self.minId<=int(x[2])<=self.maxId,
self.dataUsers))
if listUid:
return max(listUid)+1
return self.minId
def getNextGid(self):
"""get next gid"""
listGid = map(lambda x: int(x[2]),
filter(lambda x:\
self.objGroups._reNumb.match(x[2]) and\
self.minGid<=int(x[2])<=self.maxGid,
self.dataGroups))
if listGid:
return max(listGid)+1
return self.minGid
def isSystemUser(self, userName):
if filter(lambda x: x[0]==userName and int(x[2])<=self.minSysId,
self.dataUsers):
return True
return False
def addUserToDefaultGroups(self, userName):
"""Add users to groups"""
dataGroups = []
for data in self.dataGroups:
groupName = data[0]
if groupName in self.newUserGroups:
usersInGroup = data[3].split(',')
if not userName in usersInGroup:
usersInGroup.append(userName)
data[3] = ','.join(usersInGroup)
dataGroups.append(data)
self.dataGroups = dataGroups
return self.dataGroups
def changePassword(self, userName, pwdHash, maxDays="99999", warnDays="7"):
if not filter(lambda x: x[0]==userName, self.dataUsers):
self.printERROR(_("Nof found user %s")%userName)
return False
indexFoundUser = False
for i, data in enumerate(self.dataShadow):
if data[0]==userName:
indexFoundUser = i
break
#self.dataShadow = filter(lambda x: x[0]!=userName, self.dataShadow)
shadowDict = {"user":userName,
"hash":pwdHash,
"days":str(int(time.time()/86400)),
"maxDays":maxDays,
"warnDays":warnDays}
shadowLine = self.templateShadow %shadowDict
shadowList = shadowLine.split(":")
if indexFoundUser is False:
self.dataShadow.append(shadowList)
else:
self.dataShadow[indexFoundUser] = shadowList
return True
def addUser(self, userName, pwdHash):
"""Add user"""
# find user
if not filter(lambda x: x[0]==userName, self.dataUsers):
strUid = str(self.getNextUid())
strGid = str(self.getNextGid())
groupName = userName
dataExistGroup = filter(lambda x: x[0]==groupName, self.dataGroups)
if dataExistGroup:
strGid = dataExistGroup[0][2]
else:
# add group
groupDict = {"group":groupName,"gid":strGid}
groupLine = self.templateGroup %groupDict
groupList = groupLine.split(":")
self.dataGroups.append(groupList)
# add user
userDict = {"user":userName, "id":strUid, "gid":strGid}
userline = self.templateUser %userDict
userList = userline.split(":")
self.dataUsers.append(userList)
# add shadow
self.changePassword(userName, pwdHash)
# add user to defaulr groups
self.addUserToDefaultGroups(userName)
def checkPermFiles(self):
"""Check permission files"""
checkThisFiles = [migrateGroups.fileGroups, migrateUsers.filePasswd,
migrateShadow.fileShadow]
checkNewFiles = map(lambda x: pathJoin(self.prefixNewSystem,x),
checkThisFiles)
notRead = lambda x: not os.access(x, os.R_OK)
notWrite = lambda x: not os.access(x, os.W_OK)
filesNotRead = filter(notRead,checkThisFiles)
if filesNotRead:
self.printERROR(_("Can not read files") + ": " +\
", ".join(filesNotRead))
return False
filesNotWrite = filter(notWrite,checkNewFiles)
if filesNotWrite:
self.printERROR(_("Can not write to files") + ": " +\
", ".join(filesNotWrite))
return False
return True
def saveNewFiles(self):
"""Save /etc/passwd /etc/group /etc/shadow to new system"""
listFiles = map(lambda x: pathJoin(self.prefixNewSystem,x),
[migrateGroups.fileGroups, migrateUsers.filePasswd,
migrateShadow.fileShadow])
listData = [self.dataGroups, self.dataUsers, self.dataShadow]
allData = zip(listFiles,listData)
for fileName, data in allData:
buff = "\n".join(map(lambda x: ":".join(x), data)) + "\n"
FD = open(fileName, "w+")
FD.write(buff)
FD.close()
def createUserGuest(self):
if filter(lambda x: int(x[2])>=self.minSysId, self.dataUsers):
return True
else:
# add user guest
pwd = "guest"
encryptObj = encrypt()
pwdHash = encryptObj.getHashPasswd(pwd, "shadow_ssha256")
if pwdHash is False:
return False
self.addUser("guest", pwdHash)
return True
def migrate(self, addUsersList=[], pwdUsersList=[]):
"""Migrate users ang groups to new system"""
if not self.checkPermFiles():
return False
dataGroups = self.objGroups.getNewProcessedData()
dataUsers = self.objUsers.getNewProcessedData()
newSystemUsers,newUsers,thisUsers = map(lambda x: map(lambda y: y[0],x),
dataUsers)
objShadow = migrateShadow(newSystemUsers, newUsers, thisUsers,
self.prefixNewSystem)
dataShadow = objShadow.getNewProcessedData()
self.dataGroups = reduce(lambda x,y: x+y, dataGroups, [])
self.dataUsers = reduce(lambda x,y: x+y, dataUsers, [])
self.dataShadow = reduce(lambda x,y: x+y, dataShadow, [])
self.addThisUsersToGroups(thisUsers)
for userName, pwdHash in addUsersList:
if self.isSystemUser(userName):
self.printERROR(_("%s is a system user") %userName)
return False
self.addUser(userName, pwdHash)
for userName, pwdHash, maxDays, warnDays in pwdUsersList:
if not self.changePassword(userName, pwdHash,
maxDays=maxDays,
warnDays=warnDays):
return False
if not addUsersList:
# add user guest
if not self.createUserGuest():
return False
self.saveNewFiles()
return True