|
|
|
|
#-*- 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 _b64enc
|
|
|
|
|
b64encode = lambda x: _b64enc(x).rstrip()
|
|
|
|
|
try:
|
|
|
|
|
from smbpasswd import lmhash,nthash
|
|
|
|
|
except ImportError:
|
|
|
|
|
lmhash,nthash = None,None
|
|
|
|
|
from cl_print import color_print
|
|
|
|
|
# для создания сертификата
|
|
|
|
|
import pwd
|
|
|
|
|
from server.utils import execProg
|
|
|
|
|
import cl_overriding
|
|
|
|
|
import cl_lang
|
|
|
|
|
from cl_utils import genpassword, removeDir
|
|
|
|
|
|
|
|
|
|
# Перевод модуля
|
|
|
|
|
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" and lmhash:
|
|
|
|
|
hashPwd = lmhash(password)
|
|
|
|
|
elif SecHashAlg == "nt" and nthash:
|
|
|
|
|
hashPwd = nthash(password)
|
|
|
|
|
else:
|
|
|
|
|
if SecHashAlg in ("lm","nt"):
|
|
|
|
|
self.printERROR(_("ERROR") + " getHashPasswd: " +
|
|
|
|
|
(_("Can not support '%s' crypto algorithm")
|
|
|
|
|
%SecHashAlg) + " " + _("without py-smbpasswd"))
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("ERROR") + " getHashPasswd: " +
|
|
|
|
|
_("Can not support '%s' crypto algorithm")
|
|
|
|
|
%SecHashAlg)
|
|
|
|
|
return False
|
|
|
|
|
return hashPwd
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class certificate(color_print):
|
|
|
|
|
sslCountry = "RU"
|
|
|
|
|
sslState = "Saint-Petersburg"
|
|
|
|
|
sslLocality = "Saint-Petersburg"
|
|
|
|
|
sslOrganization = "Calculate Ltd."
|
|
|
|
|
sslUnit = "SSL"
|
|
|
|
|
sslCommonName = "localhost"
|
|
|
|
|
sslEmail = "support@calculate.ru"
|
|
|
|
|
nsCertType = "server"
|
|
|
|
|
sslDays = 3653
|
|
|
|
|
sslBits = 1024
|
|
|
|
|
userName = "root"
|
|
|
|
|
fileMode = 0400
|
|
|
|
|
certsDir = "/var/calculate/ssl"
|
|
|
|
|
tmpDir = os.path.join(certsDir,"tmp")
|
|
|
|
|
certFile = os.path.join(tmpDir, "server.crt")
|
|
|
|
|
keyFile = os.path.join(tmpDir, "server.key")
|
|
|
|
|
csrFile = os.path.join(tmpDir, "server.csr")
|
|
|
|
|
|
|
|
|
|
CAPath = os.path.join(certsDir,"main")
|
|
|
|
|
CACertFileName = "CA.crt"
|
|
|
|
|
CAKeyFileName = "CA.key"
|
|
|
|
|
CACrlFileName = "CA.crl"
|
|
|
|
|
rCACertPath = "crt"
|
|
|
|
|
rCAKeyPath = "key"
|
|
|
|
|
rCACrlPath = "crl"
|
|
|
|
|
rSerialFileName = "serial"
|
|
|
|
|
rDatabaseFileName = "index.dat"
|
|
|
|
|
|
|
|
|
|
sslFile = "/usr/bin/openssl"
|
|
|
|
|
|
|
|
|
|
templCnfCA = """[ ca ]
|
|
|
|
|
default_ca = CA_default
|
|
|
|
|
|
|
|
|
|
[ CA_default ]
|
|
|
|
|
dir = %(CAPath)s
|
|
|
|
|
certs = $dir/%(rCACertPath)s
|
|
|
|
|
crl_dir = $dir/%(rCACrlPath)s
|
|
|
|
|
database = $dir/%(rDatabaseFileName)s
|
|
|
|
|
new_certs_dir = $dir/%(rCACertPath)s
|
|
|
|
|
certificate = $dir/%(rCACertFile)s
|
|
|
|
|
serial = $dir/%(rSerialFileName)s
|
|
|
|
|
crlnumber = $dir/crlnumber
|
|
|
|
|
crl = $dir/%(rCACrlFile)s
|
|
|
|
|
private_key = $dir/%(rCAKeyFile)s
|
|
|
|
|
RANDFILE = $dir/%(rRandFile)s
|
|
|
|
|
|
|
|
|
|
x509_extensions = usr_cert
|
|
|
|
|
name_opt = ca_default
|
|
|
|
|
cert_opt = ca_default
|
|
|
|
|
default_days = 365
|
|
|
|
|
default_crl_days= 30
|
|
|
|
|
default_md = default
|
|
|
|
|
preserve = no
|
|
|
|
|
policy = policy_match
|
|
|
|
|
|
|
|
|
|
[ policy_match ]
|
|
|
|
|
countryName = match
|
|
|
|
|
stateOrProvinceName = match
|
|
|
|
|
organizationName = match
|
|
|
|
|
organizationalUnitName = optional
|
|
|
|
|
commonName = supplied
|
|
|
|
|
emailAddress = optional
|
|
|
|
|
|
|
|
|
|
[ policy_anything ]
|
|
|
|
|
countryName = optional
|
|
|
|
|
stateOrProvinceName = optional
|
|
|
|
|
localityName = optional
|
|
|
|
|
organizationName = optional
|
|
|
|
|
organizationalUnitName = optional
|
|
|
|
|
commonName = supplied
|
|
|
|
|
emailAddress = optional
|
|
|
|
|
|
|
|
|
|
[ usr_cert ]
|
|
|
|
|
basicConstraints=CA:FALSE
|
|
|
|
|
subjectKeyIdentifier=hash
|
|
|
|
|
authorityKeyIdentifier=keyid,issuer
|
|
|
|
|
|
|
|
|
|
[ req ]
|
|
|
|
|
prompt = no
|
|
|
|
|
default_bits = %(sslBits)s
|
|
|
|
|
x509_extensions = v3_ca
|
|
|
|
|
string_mask = utf8only
|
|
|
|
|
distinguished_name = req_dn
|
|
|
|
|
|
|
|
|
|
[ req_dn ]
|
|
|
|
|
C = %(sslCountry)s
|
|
|
|
|
ST = %(sslState)s
|
|
|
|
|
L = %(sslLocality)s
|
|
|
|
|
O = %(sslOrganization)s
|
|
|
|
|
OU = %(sslUnit)s
|
|
|
|
|
CN = %(sslCommonName)s
|
|
|
|
|
emailAddress = %(sslEmail)s
|
|
|
|
|
|
|
|
|
|
[ cert_type ]
|
|
|
|
|
nsCertType = %(nsCertType)s
|
|
|
|
|
|
|
|
|
|
[ v3_ca ]
|
|
|
|
|
subjectKeyIdentifier=hash
|
|
|
|
|
authorityKeyIdentifier=keyid:always,issuer
|
|
|
|
|
basicConstraints = CA:true
|
|
|
|
|
"""
|
|
|
|
|
templCnfData = """[ req ]
|
|
|
|
|
prompt = no
|
|
|
|
|
default_bits = %(sslBits)s
|
|
|
|
|
distinguished_name = req_dn
|
|
|
|
|
|
|
|
|
|
[ req_dn ]
|
|
|
|
|
C = %(sslCountry)s
|
|
|
|
|
ST = %(sslState)s
|
|
|
|
|
L = %(sslLocality)s
|
|
|
|
|
O = %(sslOrganization)s
|
|
|
|
|
OU = %(sslUnit)s
|
|
|
|
|
CN = %(sslCommonName)s
|
|
|
|
|
emailAddress = %(sslEmail)s
|
|
|
|
|
|
|
|
|
|
[ cert_type ]
|
|
|
|
|
nsCertType = %(nsCertType)s
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
templCreateKey = "%(sslFile)s genrsa -out '%(certKeyFile)s' %(sslBits)s"
|
|
|
|
|
templCreateCert = "%(sslFile)s req -new -x509 -days %(sslDays)s "\
|
|
|
|
|
"-config '%(cnfFile)s' -key '%(certKeyFile)s' "\
|
|
|
|
|
"-out '%(certFile)s'"
|
|
|
|
|
templCreateReq = "%(sslFile)s req -new -days %(sslDays)s "\
|
|
|
|
|
"-config '%(cnfFile)s' -key '%(certKeyFile)s' "\
|
|
|
|
|
"-out '%(certCsrFile)s'"
|
|
|
|
|
templCreateSignCert = "%(sslFile)s ca -batch -config '%(cnfFile)s' "\
|
|
|
|
|
"-policy policy_anything -days '%(sslDays)s' "\
|
|
|
|
|
"-out '%(certFile)s' -infiles '%(certCsrFile)s'"
|
|
|
|
|
|
|
|
|
|
def createCnfFile(self, textCnf):
|
|
|
|
|
'''Generate openssl.cnf file'''
|
|
|
|
|
if not os.path.exists(self.sslFile):
|
|
|
|
|
self.printERROR(_("Can not found %s")%self.sslFile)
|
|
|
|
|
return False
|
|
|
|
|
strData = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
|
|
|
|
|
cnfFileName = "%s.%s.cnf" %(strData,genpassword())
|
|
|
|
|
if not os.path.exists(self.tmpDir):
|
|
|
|
|
self._createDir(self.tmpDir)
|
|
|
|
|
cnfFile = os.path.join(self.tmpDir,cnfFileName)
|
|
|
|
|
self._createFile(cnfFile, textCnf)
|
|
|
|
|
return cnfFile
|
|
|
|
|
|
|
|
|
|
def checkCertificate(self, certFile):
|
|
|
|
|
# Проверка сертификата
|
|
|
|
|
textLine = execProg("%s x509 -subject -fingerprint -noout -in '%s'"
|
|
|
|
|
%(self.sslFile, certFile))
|
|
|
|
|
if textLine is False:
|
|
|
|
|
self.printERROR(_("Error checking certificate %s")%certFile)
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def createCertificateAutority(self,sslCountry=sslCountry,
|
|
|
|
|
sslState=sslState,
|
|
|
|
|
sslLocality=sslLocality,
|
|
|
|
|
sslOrganization=sslOrganization,
|
|
|
|
|
sslUnit=sslUnit,
|
|
|
|
|
sslCommonName=sslCommonName,
|
|
|
|
|
sslEmail=sslEmail,
|
|
|
|
|
nsCertType=nsCertType,
|
|
|
|
|
sslDays=sslDays,
|
|
|
|
|
sslBits=sslBits,
|
|
|
|
|
userName=userName,
|
|
|
|
|
CAPath=CAPath,
|
|
|
|
|
CACertFileName=CACertFileName,
|
|
|
|
|
CAKeyFileName=CAKeyFileName,
|
|
|
|
|
CACrlFileName=CACrlFileName,
|
|
|
|
|
fileMode=fileMode,
|
|
|
|
|
force=False):
|
|
|
|
|
'''Create CA'''
|
|
|
|
|
rCACertFile = os.path.join(self.rCACertPath, CACertFileName)
|
|
|
|
|
rCAKeyFile = os.path.join(self.rCAKeyPath, CAKeyFileName)
|
|
|
|
|
rCACrlFile = os.path.join(self.rCACrlPath, CACrlFileName)
|
|
|
|
|
rRandFile = os.path.join(self.rCAKeyPath,".rnd")
|
|
|
|
|
|
|
|
|
|
CACertFile = os.path.join(CAPath, rCACertFile)
|
|
|
|
|
CAKeyFile = os.path.join(CAPath, rCAKeyFile)
|
|
|
|
|
# Cerificates exists
|
|
|
|
|
if not force and os.path.isfile(CACertFile) and\
|
|
|
|
|
os.path.isfile(CAKeyFile):
|
|
|
|
|
return True
|
|
|
|
|
# получаем 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
|
|
|
|
|
# delete certificate dir
|
|
|
|
|
if os.path.isdir(CAPath):
|
|
|
|
|
removeDir(CAPath)
|
|
|
|
|
# create certificate dirs
|
|
|
|
|
self._createDir(CAPath)
|
|
|
|
|
CACertPath = os.path.join(CAPath, self.rCACertPath)
|
|
|
|
|
CAKeyPath = os.path.join(CAPath, self.rCAKeyPath)
|
|
|
|
|
CACrlPath = os.path.join(CAPath, self.rCACrlPath)
|
|
|
|
|
for createDir in [CACertPath, CAKeyPath, CACrlPath]:
|
|
|
|
|
self._createDir(createDir)
|
|
|
|
|
# save serial number
|
|
|
|
|
SerialFile = os.path.join(CAPath, self.rSerialFileName)
|
|
|
|
|
self._createFile(SerialFile, "01\n")
|
|
|
|
|
# create database file
|
|
|
|
|
DatabaseFile = os.path.join(CAPath, self.rDatabaseFileName)
|
|
|
|
|
self._createFile(DatabaseFile, "")
|
|
|
|
|
textCnf = self.templCnfCA%{'CAPath':CAPath,
|
|
|
|
|
'rCACertPath':self.rCACertPath,
|
|
|
|
|
'rCACrlPath':self.rCACrlPath,
|
|
|
|
|
'rDatabaseFileName':self.rDatabaseFileName,
|
|
|
|
|
'rCACertFile':rCACertFile,
|
|
|
|
|
'rSerialFileName':self.rSerialFileName,
|
|
|
|
|
'rCACrlFile':rCACrlFile,
|
|
|
|
|
'rCAKeyFile':rCAKeyFile,
|
|
|
|
|
'rRandFile':rRandFile,
|
|
|
|
|
'sslBits':sslBits,
|
|
|
|
|
'sslCountry':sslCountry,
|
|
|
|
|
'sslState':sslState,
|
|
|
|
|
'sslLocality':sslLocality,
|
|
|
|
|
'sslOrganization':sslOrganization,
|
|
|
|
|
'sslUnit':sslUnit,
|
|
|
|
|
'sslCommonName':sslCommonName,
|
|
|
|
|
'sslEmail':sslEmail,
|
|
|
|
|
'nsCertType':nsCertType}
|
|
|
|
|
cnfFile = self.createCnfFile(textCnf)
|
|
|
|
|
if cnfFile is False:
|
|
|
|
|
return False
|
|
|
|
|
# generate CA RSA key
|
|
|
|
|
execStr = self.templCreateKey%{'sslFile':self.sslFile,
|
|
|
|
|
'certKeyFile':CAKeyFile,
|
|
|
|
|
'sslBits':sslBits}
|
|
|
|
|
if execProg(execStr) is False:
|
|
|
|
|
self.printERROR(_("Can not execute '%s'")%execStr)
|
|
|
|
|
return False
|
|
|
|
|
if os.path.exists(CAKeyFile):
|
|
|
|
|
os.chown(CAKeyFile, uid,gid)
|
|
|
|
|
os.chmod(CAKeyFile, fileMode)
|
|
|
|
|
# create CA
|
|
|
|
|
execStr = self.templCreateCert%{'sslFile':self.sslFile,
|
|
|
|
|
'sslDays':sslDays,
|
|
|
|
|
'cnfFile':cnfFile,
|
|
|
|
|
'certKeyFile':CAKeyFile,
|
|
|
|
|
'certFile':CACertFile}
|
|
|
|
|
if execProg(execStr) is False:
|
|
|
|
|
self.printERROR(_("Can not execute '%s'")%execStr)
|
|
|
|
|
return False
|
|
|
|
|
if os.path.exists(CACertFile):
|
|
|
|
|
os.chown(CACertFile, uid,gid)
|
|
|
|
|
os.chmod(CACertFile, fileMode)
|
|
|
|
|
if os.path.exists(cnfFile):
|
|
|
|
|
os.remove(cnfFile)
|
|
|
|
|
# check certificate
|
|
|
|
|
return self.checkCertificate(CACertFile)
|
|
|
|
|
|
|
|
|
|
def createSignedCertificate(self,
|
|
|
|
|
sslCountry=sslCountry,
|
|
|
|
|
sslState=sslState,
|
|
|
|
|
sslLocality=sslLocality,
|
|
|
|
|
sslOrganization=sslOrganization,
|
|
|
|
|
sslUnit=sslUnit,
|
|
|
|
|
sslCommonName=sslCommonName,
|
|
|
|
|
sslEmail=sslEmail,
|
|
|
|
|
nsCertType=nsCertType,
|
|
|
|
|
sslDays=sslDays,
|
|
|
|
|
sslBits=sslBits,
|
|
|
|
|
userName=userName,
|
|
|
|
|
CAPath=CAPath,
|
|
|
|
|
CACertFileName=CACertFileName,
|
|
|
|
|
CAKeyFileName=CAKeyFileName,
|
|
|
|
|
CACrlFileName=CACrlFileName,
|
|
|
|
|
certFile=certFile,
|
|
|
|
|
fileMode=fileMode,
|
|
|
|
|
keyFile=keyFile,
|
|
|
|
|
csrFile=csrFile,
|
|
|
|
|
force=False):
|
|
|
|
|
'''Create signed CA certificate'''
|
|
|
|
|
certAndKeyFiles = [certFile, keyFile, csrFile]
|
|
|
|
|
foundCertFiles = map(lambda x: os.path.exists(x), certAndKeyFiles)
|
|
|
|
|
if not force and foundCertFiles[0] and foundCertFiles[1]:
|
|
|
|
|
return True
|
|
|
|
|
foundCertFiles = map(lambda x: x[1], filter(lambda x: x[0],
|
|
|
|
|
zip(foundCertFiles, certAndKeyFiles)))
|
|
|
|
|
# Удаляем файлы
|
|
|
|
|
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
|
|
|
|
|
# create dirs
|
|
|
|
|
for fileName in certAndKeyFiles:
|
|
|
|
|
dirName = os.path.split(fileName)[0]
|
|
|
|
|
if not os.path.exists(dirName):
|
|
|
|
|
self._createDir(dirName, uid=uid, gid=gid)
|
|
|
|
|
rCACertFile = os.path.join(self.rCACertPath, CACertFileName)
|
|
|
|
|
rCAKeyFile = os.path.join(self.rCAKeyPath, CAKeyFileName)
|
|
|
|
|
rCACrlFile = os.path.join(self.rCACrlPath, CACrlFileName)
|
|
|
|
|
rRandFile = os.path.join(self.rCAKeyPath,".rnd")
|
|
|
|
|
textCnf = self.templCnfCA%{'CAPath':CAPath,
|
|
|
|
|
'rCACertPath':self.rCACertPath,
|
|
|
|
|
'rCACrlPath':self.rCACrlPath,
|
|
|
|
|
'rDatabaseFileName':self.rDatabaseFileName,
|
|
|
|
|
'rCACertFile':rCACertFile,
|
|
|
|
|
'rSerialFileName':self.rSerialFileName,
|
|
|
|
|
'rCACrlFile':rCACrlFile,
|
|
|
|
|
'rCAKeyFile':rCAKeyFile,
|
|
|
|
|
'rRandFile':rRandFile,
|
|
|
|
|
'sslBits':sslBits,
|
|
|
|
|
'sslCountry':sslCountry,
|
|
|
|
|
'sslState':sslState,
|
|
|
|
|
'sslLocality':sslLocality,
|
|
|
|
|
'sslOrganization':sslOrganization,
|
|
|
|
|
'sslUnit':sslUnit,
|
|
|
|
|
'sslCommonName':sslCommonName,
|
|
|
|
|
'sslEmail':sslEmail,
|
|
|
|
|
'nsCertType':nsCertType}
|
|
|
|
|
cnfFile = self.createCnfFile(textCnf)
|
|
|
|
|
if cnfFile is False:
|
|
|
|
|
return False
|
|
|
|
|
# generate RSA key
|
|
|
|
|
execStr = self.templCreateKey%{'sslFile':self.sslFile,
|
|
|
|
|
'certKeyFile':keyFile,
|
|
|
|
|
'sslBits':sslBits}
|
|
|
|
|
if execProg(execStr) is False:
|
|
|
|
|
self.printERROR(_("Can not execute '%s'")%execStr)
|
|
|
|
|
return False
|
|
|
|
|
if os.path.exists(keyFile):
|
|
|
|
|
os.chown(keyFile, uid,gid)
|
|
|
|
|
os.chmod(keyFile, fileMode)
|
|
|
|
|
# generate request
|
|
|
|
|
execStr = self.templCreateReq%{'sslFile':self.sslFile,
|
|
|
|
|
'sslDays':sslDays,
|
|
|
|
|
'cnfFile':cnfFile,
|
|
|
|
|
'certKeyFile':keyFile,
|
|
|
|
|
'certCsrFile':csrFile}
|
|
|
|
|
if execProg(execStr) is False:
|
|
|
|
|
self.printERROR(_("Can not execute '%s'")%execStr)
|
|
|
|
|
return False
|
|
|
|
|
if os.path.exists(csrFile):
|
|
|
|
|
os.chown(csrFile, uid,gid)
|
|
|
|
|
os.chmod(csrFile, fileMode)
|
|
|
|
|
# set database attribute
|
|
|
|
|
databaseAttrFileName = os.path.join(CAPath, "index.dat.attr")
|
|
|
|
|
self._createFile(databaseAttrFileName, "unique_subject = no\n")
|
|
|
|
|
# generate signed cerificate
|
|
|
|
|
execStr = self.templCreateSignCert%{'sslFile':self.sslFile,
|
|
|
|
|
'sslDays':sslDays,
|
|
|
|
|
'cnfFile':cnfFile,
|
|
|
|
|
'certFile':certFile,
|
|
|
|
|
'certCsrFile':csrFile}
|
|
|
|
|
if execProg(execStr) is False:
|
|
|
|
|
self.printERROR(_("Can not execute '%s'")%execStr)
|
|
|
|
|
return False
|
|
|
|
|
if os.path.exists(certFile):
|
|
|
|
|
os.chown(certFile, uid,gid)
|
|
|
|
|
os.chmod(certFile, fileMode)
|
|
|
|
|
if os.path.exists(cnfFile):
|
|
|
|
|
os.remove(cnfFile)
|
|
|
|
|
# check certificate
|
|
|
|
|
return self.checkCertificate(certFile)
|
|
|
|
|
|
|
|
|
|
def createCertificate(self,
|
|
|
|
|
sslCountry=sslCountry,
|
|
|
|
|
sslState=sslCountry,
|
|
|
|
|
sslLocality=sslLocality,
|
|
|
|
|
sslOrganization=sslOrganization,
|
|
|
|
|
sslUnit=sslUnit,
|
|
|
|
|
sslCommonName=sslCommonName,
|
|
|
|
|
sslEmail=sslEmail,
|
|
|
|
|
nsCertType=nsCertType,
|
|
|
|
|
sslDays=sslDays,
|
|
|
|
|
sslBits=sslBits,
|
|
|
|
|
userName=userName,
|
|
|
|
|
certFile=certFile,
|
|
|
|
|
fileMode=fileMode,
|
|
|
|
|
keyFile=keyFile):
|
|
|
|
|
"""Создает сертификат"""
|
|
|
|
|
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=self.templCnfData%{'sslBits':sslBits,
|
|
|
|
|
'sslCountry':sslCountry,
|
|
|
|
|
'sslState':sslState,
|
|
|
|
|
'sslLocality':sslLocality,
|
|
|
|
|
'sslOrganization':sslOrganization,
|
|
|
|
|
'sslUnit':sslUnit,
|
|
|
|
|
'sslCommonName':sslCommonName,
|
|
|
|
|
'sslEmail':sslEmail,
|
|
|
|
|
'nsCertType':nsCertType}
|
|
|
|
|
cnfFile = self.createCnfFile(textCnf)
|
|
|
|
|
if cnfFile is False:
|
|
|
|
|
return False
|
|
|
|
|
# Cоздание директорий
|
|
|
|
|
for fileName in certAndKeyFiles:
|
|
|
|
|
dirName = os.path.split(fileName)[0]
|
|
|
|
|
if not os.path.exists(dirName):
|
|
|
|
|
self._createDir(dirName, uid=uid, gid=gid)
|
|
|
|
|
# Создание сертификата
|
|
|
|
|
textLine = execProg("%s req -new -x509 -nodes -config '%s'"
|
|
|
|
|
"-days %s -out '%s'-keyout '%s'"
|
|
|
|
|
%(self.sslFile, cnfFile, sslDays, certFile,
|
|
|
|
|
keyFile))
|
|
|
|
|
if textLine is False:
|
|
|
|
|
self.printERROR(_("Can not create certificate %s")%certFile)
|
|
|
|
|
return False
|
|
|
|
|
# Удаление конфигурационного файла
|
|
|
|
|
if os.path.exists(cnfFile):
|
|
|
|
|
os.remove(cnfFile)
|
|
|
|
|
# Меняем права
|
|
|
|
|
if os.path.exists(certFile):
|
|
|
|
|
os.chown(certFile, uid,gid)
|
|
|
|
|
os.chmod(certFile, fileMode)
|
|
|
|
|
if os.path.exists(keyFile):
|
|
|
|
|
os.chown(keyFile, uid,gid)
|
|
|
|
|
os.chmod(keyFile, fileMode)
|
|
|
|
|
|
|
|
|
|
return self.checkCertificate(certFile)
|
|
|
|
|
|
|
|
|
|
def _createDir(self, dirName, uid=0, gid=0, 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=0, gid=0, mode=0600):
|
|
|
|
|
"""Создает пользовательский файл с содержимым
|
|
|
|
|
|
|
|
|
|
Если директория файла не существует то ошибка
|
|
|
|
|
"""
|
|
|
|
|
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, 0600)
|
|
|
|
|
os.chown(fileName,uid,gid)
|
|
|
|
|
if fileTxt:
|
|
|
|
|
FD = open(fileName, "r+")
|
|
|
|
|
FD.write(fileTxt)
|
|
|
|
|
FD.close()
|
|
|
|
|
os.chmod(fileName, mode)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getHash(password, encr):
|
|
|
|
|
"""Получить хеш пароля
|
|
|
|
|
|
|
|
|
|
password - пароль
|
|
|
|
|
encr - алгоритм шифрования, например 'ssha'
|
|
|
|
|
"""
|
|
|
|
|
encryptObj = encrypt()
|
|
|
|
|
hashPwd = encryptObj.getHashPasswd(password, encr.lower())
|
|
|
|
|
if hashPwd:
|
|
|
|
|
return hashPwd
|
|
|
|
|
else:
|
|
|
|
|
encryptObj.printERROR(_("Error encrypt password, "
|
|
|
|
|
"method getHash()"))
|
|
|
|
|
cl_overriding.exit(1)
|