#-*- coding: utf-8 -*- # Copyright 2008-2010 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, len=2): """Генерация соли для хеширования пароля (CRYPT)""" chars = string.letters + string.digits + "./" salt = "" for i in range(len): salt = salt + choice(chars) return salt def getHashPasswd(self, password, SecHashAlg): """Генерация хеша пароля, Поддерживаемые алгоритмы шифрования пароля: plain, md5, smd5, crypt, sha, ssha, lm, nt, shadow_ssha512, shadow_ssha256, shadow_md5 """ 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 == "shadow_ssha512": salt = self.__GenCryptSalt__(8) hashPwd = crypt.crypt(password, "$6$%s$"%salt) elif SecHashAlg == "shadow_ssha256": salt = self.__GenCryptSalt__(8) hashPwd = crypt.crypt(password, "$5$%s$"%salt) elif SecHashAlg == "shadow_md5": salt = self.__GenCryptSalt__(8) hashPwd = crypt.crypt(password, "$1$%s$"%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