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.
307 lines
9.9 KiB
307 lines
9.9 KiB
#!/usr/bin/python
|
|
#-*- coding: utf-8 -*-
|
|
|
|
# Copyright 2012 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, os
|
|
import socket, ssl
|
|
from cherrypy.wsgiserver import CherryPyWSGIServer, WSGIPathInfoDispatcher
|
|
from cherrypy.wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter
|
|
from OpenSSL.SSL import Error as SSLError
|
|
from OpenSSL import SSL
|
|
import OpenSSL
|
|
import importlib
|
|
from signal import SIGTERM
|
|
import threading
|
|
|
|
from calculate.lib.datavars import DataVars
|
|
from calculate.core.datavars import DataVarsCore
|
|
|
|
from clean import clean
|
|
import cert_cmd
|
|
import bootstrap
|
|
|
|
from func import initialization
|
|
from server_class import ClApplication
|
|
|
|
class OpenSSLAdapter (pyOpenSSLAdapter):
|
|
|
|
#def check_cert(self, cert):
|
|
#if cert == None:
|
|
#return -1
|
|
#cert_id = 0
|
|
|
|
#from func import find_cert_id
|
|
#find_cert_id(cert, self.data_path, self.certbase)
|
|
## open database with certificates
|
|
|
|
#if not os.path.exists(self.certbase):
|
|
#fc = open(self.certbase,"w")
|
|
#fc.close()
|
|
#fc = open(self.certbase,"r")
|
|
|
|
#while 1:
|
|
#try:
|
|
## read all on one record
|
|
#cert_dict = pickle.load(fc)
|
|
#except:
|
|
#break
|
|
## if input and cert from database equal
|
|
#if cert == cert_dict["cert"]:
|
|
## get certificate id
|
|
#cert_id = cert_dict["Id"]
|
|
#fc.close()
|
|
#return cert_id
|
|
|
|
def verify_func(self, connection, x509, errnum, errdepth, ok):
|
|
# get client certificate
|
|
curThread = threading.currentThread()
|
|
#print '#######################',errdepth,'####################################'
|
|
#if not OpenSSL.crypto.dump_certificate \
|
|
#(OpenSSL.crypto.FILETYPE_PEM, x509) in self.ca_certs:
|
|
#print '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
|
|
#return 0
|
|
if errdepth == 0:
|
|
curThread.client_cert = OpenSSL.crypto.dump_certificate \
|
|
(OpenSSL.crypto.FILETYPE_PEM, x509)
|
|
#cert = OpenSSL.crypto.load_certificate(OpenSSL.SSL.FILETYPE_PEM,
|
|
#curThread.client_cert)
|
|
#subject = cert.get_subject()
|
|
|
|
#if ok:
|
|
#try:
|
|
#country = len (subject.get_components()) - 1
|
|
#language = 1
|
|
#curThread.lang = subject.get_components()[country][language]
|
|
#except:
|
|
#curThread.lang = "En"
|
|
else:
|
|
curThread.client_cert = None
|
|
return ok
|
|
|
|
def get_context(self):
|
|
"""Return an SSL.Context from self attributes."""
|
|
# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473
|
|
|
|
c = SSL.Context(SSL.SSLv23_METHOD)
|
|
c.use_privatekey_file(self.private_key)
|
|
c.set_verify(SSL.VERIFY_PEER, self.verify_func)
|
|
|
|
if self.certificate_chain:
|
|
c.load_verify_locations(self.certificate_chain)
|
|
|
|
c.use_certificate_file(self.certificate)
|
|
return c
|
|
|
|
def main(*args, **keywords):
|
|
# For cleaning of sessions at server reboot
|
|
args = cert_cmd.parse()
|
|
|
|
# translate
|
|
if args.lang:
|
|
translate(args.lang)
|
|
|
|
debug = args.debug
|
|
|
|
import logging
|
|
import logging.handlers
|
|
|
|
if not os.path.exists('/var/log/calculate'):
|
|
os.makedirs('/var/log/calculate')
|
|
LOG_FILENAME = '/var/log/calculate/logging_cl_core_server.out'
|
|
file_logger = logging.getLogger('MyLogger')
|
|
file_logger.setLevel(logging.DEBUG)
|
|
|
|
# Add the log message handler to the logger
|
|
handler = logging.handlers.RotatingFileHandler(
|
|
LOG_FILENAME, maxBytes=10000000, backupCount=3)
|
|
|
|
file_logger.addHandler(handler)
|
|
|
|
# debug
|
|
if debug:
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
logger = logging.getLogger('soaplib.wsgi')
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
port = args.port
|
|
ob = DataVarsApi()
|
|
ob.importApi()
|
|
|
|
# set var env
|
|
ob.flIniFile()
|
|
cl_wsdl = ob.Get('cl_wsdl')
|
|
data_path = ob.Get('cl_core_data')
|
|
certbase = ob.Get('cl_core_database')
|
|
serv_certbase = ob.Get('cl_core_serv_database')
|
|
rights = ob.Get('cl_core_rights')
|
|
group_rights = ob.Get('cl_core_group_rights')
|
|
sids = ob.Get('cl_core_sids_path')
|
|
pids = ob.Get('cl_core_pids_path')
|
|
sids_pids = ob.Get('cl_core_sids_pids')
|
|
sids_file = ob.Get('cl_core_sids_file')
|
|
pids_file = ob.Get('cl_core_pids_file')
|
|
max_sid = ob.Get('cl_core_max_sid')
|
|
max_pid = ob.Get('cl_core_max_pid')
|
|
cert_path = ob.Get('cl_core_cert_path')
|
|
cert = ob.Get('cl_core_cert')
|
|
key = ob.Get('cl_core_key')
|
|
cl_ver = ob.Get('cl_ver')
|
|
|
|
# delete all sid and pid informations file
|
|
clean(sids_file, pids_file, sids_pids, sids, pids)
|
|
|
|
cert_cmd.create_path(data_path, certbase, rights, group_rights)
|
|
#####################
|
|
''' view information about client certificates '''
|
|
if args.version:
|
|
print cl_ver
|
|
return 0
|
|
if args.bootstrap_user_name:
|
|
bootstrap.init(cert, key, cert_path, data_path, certbase, args, port,\
|
|
args.bootstrap_user_name)
|
|
return 0
|
|
if args.revoke_cert_id:
|
|
cert_cmd.revoke_signed_cert(args.revoke_cert_id, data_path, cert_path)
|
|
return 0
|
|
if args.host or args.gen_root_cert or args.root_host or args.use_root_cert:
|
|
cert_cmd.check_server_certificate(cert, key, cert_path, args, port)
|
|
return 0
|
|
if args.id_client_req:
|
|
cert_cmd.sing_req_by_server(args.id_client_req, cert_path, data_path)
|
|
return 0
|
|
if args.Id:
|
|
cert_cmd.view_cert(args, certbase, data_path, rights, group_rights)
|
|
return 0
|
|
if args.cert_id:
|
|
cert_cmd.view_signed_cert(args, serv_certbase, data_path)
|
|
return 0
|
|
if args.req_id:
|
|
cert_cmd.view_client_request(args, certbase, data_path)
|
|
return 0
|
|
# Sign request by root certificate
|
|
if args.id_server_req:
|
|
cert_cmd.sing_req_by_root(args, cert_path, data_path)
|
|
return 0
|
|
if args.id_del_req:
|
|
cert_cmd.del_request(args.id_del_req, serv_certbase, data_path)
|
|
return 0
|
|
|
|
#####################
|
|
|
|
# importing other modules
|
|
other_mod = initialization(cl_wsdl)
|
|
#try:
|
|
pack = "calculate.core.server"
|
|
func_metaclass = importlib.import_module('%s.func_metaclass' %pack)
|
|
|
|
other_mod.append(func_metaclass.Func_MetaClass)
|
|
|
|
from calculate.core.server.cl_vers_api import VERS
|
|
other_mod.append(VERS)
|
|
|
|
from calculate.core.server.baseClass import Basic
|
|
other_mod.append(Basic)
|
|
other_mod.append(object)
|
|
# make server metaclass
|
|
CombinedServerClass = type ("CombinedServerClass", tuple(other_mod), {})
|
|
|
|
App = ClApplication([CombinedServerClass],'tns', log = file_logger)
|
|
tc = App.get_service(CombinedServerClass)
|
|
# set all path
|
|
tc.set_paths (data_path, certbase, serv_certbase, rights, group_rights, \
|
|
sids, pids, sids_pids, sids_file, pids_file, max_sid, \
|
|
max_pid, cert_path, cert, key)
|
|
|
|
max_num = 99999999
|
|
dispatcher = WSGIPathInfoDispatcher( { '' : App } )
|
|
server = CherryPyWSGIServer(('0.0.0.0', port), dispatcher,\
|
|
numthreads = 10, max = max_num, request_queue_size = max_num)
|
|
|
|
print _("listening to https://0.0.0.0:%d") % (port)
|
|
print _("wsdl is at: https://0.0.0.0:%d/?wsdl") %(port)
|
|
|
|
ca_cert = cert_path + "/ca_root.crt"
|
|
if not os.path.exists (ca_cert):
|
|
ca_cert = None
|
|
|
|
sslAdapter = OpenSSLAdapter(cert, key, ca_cert)
|
|
|
|
sslAdapter.certbase = certbase
|
|
|
|
server.ssl_adapter = sslAdapter
|
|
server.certbase = certbase
|
|
server.serv_certbase = serv_certbase
|
|
server.rights = rights
|
|
server.group_rights = group_rights
|
|
server.sids = sids
|
|
server.pids = pids
|
|
server.sids_file = sids_file
|
|
server.pids_file = pids_file
|
|
server.data_path = data_path
|
|
server.cert_path = cert_path
|
|
|
|
server.ssl_certificate = cert
|
|
server.ssl_private_key = key
|
|
|
|
try:
|
|
print _("Server start")
|
|
server.start()
|
|
except KeyboardInterrupt, SIGTERM:
|
|
try:
|
|
tc.killall()
|
|
except KeyboardInterrupt:
|
|
pass
|
|
print _("\nServer stopping")
|
|
server.stop()
|
|
sys.exit(0)
|
|
except socket.error, e:
|
|
print e
|
|
except SSLError, e:
|
|
print '\n',_('Server certificate not found')#, e
|
|
print _('use cl-core with key --gen-cert-by HOST '
|
|
'(--get-cert-from HOST) '
|
|
'or --use-root-as-server)')
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
server.stop()
|
|
sys.exit(0)
|
|
|
|
def translate(lang = None):
|
|
import locale
|
|
import gettext
|
|
|
|
if lang:
|
|
try:
|
|
language = gettext.translation ('cl_core', languages = [lang])
|
|
language.install()
|
|
return 0
|
|
except:
|
|
print "lang %s not supported!" %str(lang)
|
|
|
|
try:
|
|
current_locale, encoding = locale.getdefaultlocale()
|
|
|
|
language = gettext.translation ('cl_core', \
|
|
languages = [current_locale] )
|
|
language.install()
|
|
return 0
|
|
except:
|
|
language = gettext.translation ('cl_core', languages = ['en'] )
|
|
language.install()
|
|
return 0
|
|
#print _("set locale"), current_locale
|