This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/servers/Gateway/Gateway.py

261 lines
9.0 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Authentication Server"""
__version__ = '$Revision$'[11:-2]
import getopt
import os
import signal
import sys
import traceback
try:
from M2Crypto import SSL
except ImportError:
SSL = None
glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
sys.path.insert(0, glasnostPythonDir)
import glasnost
import glasnost.common.applications as applications
import glasnost.common.context as context
import glasnost.common.tools_new as commonTools
from glasnost.server.tools import *
from glasnost.proxy.DispatcherProxy import callServer
class Gateway(applications.Application):
applicationName = 'Gateway'
applicationRole = 'gateway'
hostName = None
port = None
publicPort = None
rpcServer = None
def callGateway(self, virtualServerId, clientToken, userToken, serverId,
functionName, arguments):
# Remove the port (if any) from the serverId, because the public port
# of the gateway is the same as the serverPort of the dispatcher.
# So we ensure that the Gateway wont call itself endlessly instead of
# the dispatcher.
# The removal of the port is also good for security reasons.
# the same port of the dispatcherId
realServerId = commonTools.makeApplicationId(
'glasnost://%s' % extractApplicationHostName(serverId),
commonTools.extractRole(serverId))
arguments[0] = realServerId
dispatcherId = commonTools.extractDispatcherId(virtualServerId)
context.push(
_level = 'callGateway',
applicationToken = clientToken,
dispatcherId = dispatcherId,
userToken = userToken,
)
try:
return callServer(realServerId, functionName, arguments)
finally:
context.pull(_level = 'callGateway')
def getServerAccessor(self, virtualServerId, clientToken, userToken,
serverId):
return {
'isGateway': 1,
'serverHostName': self.hostName,
'serverPort': self.publicPort,
}
def handleGetopt(self):
try:
opts, args = getopt.getopt(
sys.argv[1:],
'd:hi:s:x:y:',
['destination=', 'export=', 'help', 'import=', 'source=',
'system='])
except getopt.GetoptError:
self.usage()
return 2
if len(args) != 0:
self.usage()
return 2
destinationDispatcherId = None
doExport = 0
doImport = 0
doSystem = 0
exportDirectoryPath = None
importDirectoryPath = None
sourceDispatcherId = None
for o, a in opts:
if o in ('-d', '--destination'):
destinationDispatcherId = a
if destinationDispatcherId[-1] == '/':
destinationDispatcherId = destinationDispatcherId[:-1]
if o in ('-h', '--help'):
usage()
return 0
if o in ('-i', '--import'):
importDirectoryPath = a
doImport = 1
if o in ('-s', '--source'):
sourceDispatcherId = a
if sourceDispatcherId[-1] == '/':
sourceDispatcherId = sourceDispatcherId[:-1]
if o in ('-x', '--export'):
exportDirectoryPath = a
doExport = 1
if o in ('-y', '--system'):
doSystem = 1
if doImport or doExport or doSystem:
return 0
if sourceDispatcherId and destinationDispatcherId:
return 0
return None
def handleSignal(self, signalNumber, stackFrame):
if signalNumber == signal.SIGINT:
raise KeyboardInterrupt
if signalNumber == signal.SIGHUP:
self.setLogFile()
return
if signalNumber == signal.SIGTERM:
print 'Received signal SIGTERM: exiting.'
os._exit(0)
def launch(self):
applications.Application.launch(self)
goDaemon()
self.setLogFile()
self.startRpcServer()
self.run()
def loadConfigOptions(self):
applications.Application.loadConfigOptions(self)
configContext = context.get(_level = 'config')
self.hostName = commonTools.getConfig(
self.applicationName, 'ServerHostName')
if not self.hostName:
self.hostName = 'localhost'
try:
self.port = eval(commonTools.getConfig(
self.applicationName, 'ServerPort'), {})
except TypeError:
if self.port is not None:
del self.port
try:
self.publicPort = eval(commonTools.getConfig(
self.applicationName, 'PublicPort'), {})
except TypeError:
if self.publicPort is not None:
del self.publicPort
def registerPublicMethod(self, methodName, method = None):
if method is None:
method = getattr(self, methodName)
self.rpcServer.add_method(methodName, method, help = method.__doc__)
def registerPublicMethods(self):
self.registerPublicMethod('callGateway')
self.registerPublicMethod('getServerAccessor')
def run(self):
signal.signal(signal.SIGINT, self.handleSignal)
signal.signal(signal.SIGHUP, self.handleSignal)
signal.signal(signal.SIGTERM, self.handleSignal)
self.rpcServer.baseContext = context.get()
while 1:
try:
self.rpcServer.serve_forever()
except KeyboardInterrupt:
break
except:
traceback.print_exc()
del self.rpcServer.baseContext
def startRpcServer(self):
if SSL:
from glasnost.server.xmlrpcServer import XmlRpcSslThreadingServer
certificatePath = '/etc/%s/server.pem' % glasnost.applicationName
certificateAutorityPath = '/etc/%s/ca.pem' \
% glasnost.applicationName
verifyDepth = 10
sslContext = SSL.Context('sslv2')
sslContext.load_cert(certificatePath)
sslContext.load_client_ca(certificateAutorityPath)
sslContext.load_verify_info(certificateAutorityPath)
sslContext.set_verify(SSL.verify_none, verifyDepth)
sslContext.set_allow_unknown_ca(1)
sslContext.set_session_id_ctx('xmlrpc')
sslContext.set_info_callback()
self.rpcServer = XmlRpcSslThreadingServer(
('', self.port), sslContext = sslContext)
else:
from glasnost.server.xmlrpcServer import XmlRpcThreadingServer
self.rpcServer = XmlRpcThreadingServer(('', self.port))
self.registerPublicMethods()
# Don't call registerServer, because the gateway can only be called
# from the outside, not from the other Glasnost servers.
def usage(self):
print 'Usage: %s ### FIXME: To Do' % self.applicationName
gateway = Gateway()
if __name__ == "__main__":
gateway.launch()