|
|
|
|
#-*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
# Copyright 2008-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 sys
|
|
|
|
|
import os
|
|
|
|
|
import hashlib
|
|
|
|
|
import crypt
|
|
|
|
|
import string
|
|
|
|
|
import time
|
|
|
|
|
from random import choice
|
|
|
|
|
from base64 import encodestring as b64encode
|
|
|
|
|
import smbpasswd
|
|
|
|
|
from cl_print import color_print
|
|
|
|
|
# для создания сертификата
|
|
|
|
|
import pwd
|
|
|
|
|
from server.utils import execProg
|
|
|
|
|
import cl_lang
|
|
|
|
|
# Перевод модуля
|
|
|
|
|
tr = cl_lang.lang()
|
|
|
|
|
tr.setLocalDomain('cl_lib')
|
|
|
|
|
tr.setLanguage(sys.modules[__name__])
|
|
|
|
|
|
|
|
|
|
class encrypt(color_print):
|
|
|
|
|
"""Класс хранения общих методов используемых для настройки сервисов
|
|
|
|
|
|
|
|
|
|
Методы шифрования, создания сертификатов и.т. д
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __GenCryptSalt__(self):
|
|
|
|
|
"""Генерация соли для хеширования пароля (CRYPT)"""
|
|
|
|
|
chars = string.letters + string.digits + "./"
|
|
|
|
|
salt = ""
|
|
|
|
|
for i in range(2):
|
|
|
|
|
salt = salt + choice(chars)
|
|
|
|
|
return salt
|
|
|
|
|
|
|
|
|
|
def getHashPasswd(self, password, SecHashAlg):
|
|
|
|
|
"""Генерация хеша пароля,
|
|
|
|
|
|
|
|
|
|
Поддерживаемые алгоритмы шифрования пароля:
|
|
|
|
|
plain, md5, smd5, crypt, sha, ssha, lm, nt
|
|
|
|
|
"""
|
|
|
|
|
if not password:
|
|
|
|
|
self.printERROR(_("ERROR") + " getHashPasswd: " +\
|
|
|
|
|
_("password empty"))
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
hashPwd = ""
|
|
|
|
|
if SecHashAlg == "plain":
|
|
|
|
|
hashPwd = password
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "md5":
|
|
|
|
|
h = hashlib.md5(password)
|
|
|
|
|
hashPwd = "{MD5}" + b64encode(h.digest())
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "smd5":
|
|
|
|
|
salt = os.urandom(4)
|
|
|
|
|
h = hashlib.md5(password)
|
|
|
|
|
h.update(salt)
|
|
|
|
|
hashPwd = "{SMD5}" + b64encode(h.digest() + salt)
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "crypt":
|
|
|
|
|
salt = self.__GenCryptSalt__()
|
|
|
|
|
hashPwd = "{CRYPT}" + crypt.crypt(password, salt)
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "sha":
|
|
|
|
|
h = hashlib.sha1(password)
|
|
|
|
|
hashPwd = "{SHA}" + b64encode(h.digest())
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "ssha":
|
|
|
|
|
salt = os.urandom(4)
|
|
|
|
|
h = hashlib.sha1(password)
|
|
|
|
|
h.update(salt)
|
|
|
|
|
hashPwd = "{SSHA}" + b64encode(h.digest() + salt)
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "lm":
|
|
|
|
|
hashPwd = smbpasswd.lmhash(password)
|
|
|
|
|
|
|
|
|
|
elif SecHashAlg == "nt":
|
|
|
|
|
hashPwd = smbpasswd.nthash(password)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("ERROR") + " getHashPasswd: " +\
|
|
|
|
|
_("Can not support '%s' crypto algorithm")\
|
|
|
|
|
%SecHashAlg)
|
|
|
|
|
return False
|
|
|
|
|
return hashPwd
|
|
|
|
|
|
|
|
|
|
def createCertificate(self, sslCountry="US",
|
|
|
|
|
sslState="California",
|
|
|
|
|
sslLocality="Santa Barbara",
|
|
|
|
|
sslOrganization="SSL Server",
|
|
|
|
|
sslUnit="For Testing Purposes Only",
|
|
|
|
|
sslCommonName="localhost",
|
|
|
|
|
sslEmail="root@localhost",
|
|
|
|
|
nsCertType="server",
|
|
|
|
|
sslDays=730,
|
|
|
|
|
sslBits=1024,
|
|
|
|
|
userName="root",
|
|
|
|
|
certFile="/tmp/server.pem",
|
|
|
|
|
certFileMode=0400,
|
|
|
|
|
keyFile="/tmp/server.key",
|
|
|
|
|
keyFileMode=0400):
|
|
|
|
|
"""Создает сертификат"""
|
|
|
|
|
certAndKeyFiles = [certFile, keyFile]
|
|
|
|
|
foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles)
|
|
|
|
|
if len(foundCertFiles)==2:
|
|
|
|
|
return True
|
|
|
|
|
# Удаляем файл сертификата
|
|
|
|
|
map(lambda x: os.remove(x), foundCertFiles)
|
|
|
|
|
# получаем id и gid пользователя
|
|
|
|
|
try:
|
|
|
|
|
pwdObj = pwd.getpwnam(userName)
|
|
|
|
|
except:
|
|
|
|
|
self.printERROR(_("Not found user %s")%userName)
|
|
|
|
|
return False
|
|
|
|
|
uid = pwdObj.pw_uid
|
|
|
|
|
gid = pwdObj.pw_gid
|
|
|
|
|
textCnf="""[ req ]
|
|
|
|
|
prompt = no
|
|
|
|
|
default_bits = %s
|
|
|
|
|
distinguished_name = req_dn
|
|
|
|
|
|
|
|
|
|
[ req_dn ]
|
|
|
|
|
C = %s
|
|
|
|
|
ST = %s
|
|
|
|
|
L = %s
|
|
|
|
|
O = %s
|
|
|
|
|
OU = %s
|
|
|
|
|
CN = %s
|
|
|
|
|
emailAddress = %s
|
|
|
|
|
|
|
|
|
|
[ cert_type ]
|
|
|
|
|
nsCertType = %s
|
|
|
|
|
"""%(sslBits, sslCountry, sslState, sslLocality, sslOrganization, sslUnit,
|
|
|
|
|
sslCommonName, sslEmail, nsCertType)
|
|
|
|
|
# генерируем название файла конфигурации
|
|
|
|
|
strData = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
|
|
|
|
|
cnfFile = "/tmp/%s.cnf" %strData
|
|
|
|
|
sslFile = "/usr/bin/openssl"
|
|
|
|
|
if not os.path.exists(sslFile):
|
|
|
|
|
self.printERROR(_("Can not found %s")%sslFile)
|
|
|
|
|
return False
|
|
|
|
|
# Cоздание директорий
|
|
|
|
|
for fileName in certAndKeyFiles:
|
|
|
|
|
dirName = os.path.split(fileName)[0]
|
|
|
|
|
if not os.path.exists(dirName):
|
|
|
|
|
self._createDir(0, 0, dirName, 0755)
|
|
|
|
|
# Создание конфигурационного файла
|
|
|
|
|
self._createFile(cnfFile, textCnf, 0, 0, 0600)
|
|
|
|
|
# Создание сертификата
|
|
|
|
|
textLine = execProg(\
|
|
|
|
|
"%s req -new -x509 -nodes -config %s -days %s -out %s -keyout %s"\
|
|
|
|
|
%(sslFile, cnfFile, sslDays, certFile, keyFile))
|
|
|
|
|
# Удаление конфигурационного файла
|
|
|
|
|
if os.path.exists(cnfFile):
|
|
|
|
|
os.remove(cnfFile)
|
|
|
|
|
# Меняем права
|
|
|
|
|
if os.path.exists(certFile):
|
|
|
|
|
os.chown(certFile, uid,gid)
|
|
|
|
|
os.chmod(certFile, certFileMode)
|
|
|
|
|
if os.path.exists(keyFile):
|
|
|
|
|
os.chown(keyFile, uid,gid)
|
|
|
|
|
os.chmod(keyFile, keyFileMode)
|
|
|
|
|
if textLine is False:
|
|
|
|
|
self.printERROR(_("Can not create certificate %s")%certFile)
|
|
|
|
|
return False
|
|
|
|
|
# Проверка сертификата
|
|
|
|
|
textLine = execProg("%s x509 -subject -fingerprint -noout -in %s"\
|
|
|
|
|
%(sslFile, certFile))
|
|
|
|
|
if textLine is False:
|
|
|
|
|
self.printERROR(_("Can not create certificate %s")%certFile)
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def _createDir(self, uid, gid, dirName, mode=0700):
|
|
|
|
|
"""Создание пользовательской директории"""
|
|
|
|
|
if not os.path.exists(dirName):
|
|
|
|
|
os.makedirs(dirName)
|
|
|
|
|
if mode:
|
|
|
|
|
os.chmod(dirName,mode)
|
|
|
|
|
os.chown(dirName,uid,gid)
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("Path %s exists") %dirName)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def _createFile(self, fileName, fileTxt, uid, gid, mode=0644):
|
|
|
|
|
"""Создает пользовательский файл с содержимым
|
|
|
|
|
|
|
|
|
|
Если директория файла не существует то ошибка
|
|
|
|
|
"""
|
|
|
|
|
dirName = os.path.split(fileName)[0]
|
|
|
|
|
if not os.path.exists(dirName):
|
|
|
|
|
self.printERROR(_("Path %s not exists") %dirName)
|
|
|
|
|
return False
|
|
|
|
|
fd = os.open(fileName, os.O_CREAT)
|
|
|
|
|
os.close(fd)
|
|
|
|
|
os.chmod(fileName, mode)
|
|
|
|
|
os.chown(fileName,uid,gid)
|
|
|
|
|
if fileTxt:
|
|
|
|
|
FD = open(fileName, "r+")
|
|
|
|
|
FD.write(fileTxt)
|
|
|
|
|
FD.close()
|
|
|
|
|
return True
|