[X2Go-Commits] x2gobroker.git - build-main (branch) updated: 01ed711dba1fea373f1b212b40c1a50f61436ed4
X2Go dev team
git-admin at x2go.org
Sun May 19 13:04:30 CEST 2013
The branch, build-main has been updated
via 01ed711dba1fea373f1b212b40c1a50f61436ed4 (commit)
from 92a791df1fcefa36560ed18b326ab0cc1ea5a5f2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
etc/x2gobroker.conf | 4 +-
sbin/x2gobroker | 153 ++++----------
x2gobroker/{ => backends}/__init__.py | 3 -
x2gobroker/{ => backends}/base.py | 88 ++++++---
x2gobroker/{ => backends}/ldap.py | 0
x2gobroker/{ => backends}/simple.py | 20 +-
x2gobroker/{ => backends}/zeroconf.py | 18 +-
x2gobroker/config.py | 308 +++++++++++++++++++++++++++++
x2gobroker/defaults.py | 13 +-
x2gobroker/utils.py | 82 ++++++++
x2gobroker/{ => web}/__init__.py | 3 -
sbin/x2gobroker => x2gobroker/web/html.py | 121 ++++++------
x2gobroker/{__init__.py => web/json.py} | 12 +-
13 files changed, 587 insertions(+), 238 deletions(-)
copy x2gobroker/{ => backends}/__init__.py (97%)
rename x2gobroker/{ => backends}/base.py (61%)
rename x2gobroker/{ => backends}/ldap.py (100%)
rename x2gobroker/{ => backends}/simple.py (71%)
rename x2gobroker/{ => backends}/zeroconf.py (77%)
create mode 100644 x2gobroker/config.py
create mode 100644 x2gobroker/utils.py
copy x2gobroker/{ => web}/__init__.py (97%)
copy sbin/x2gobroker => x2gobroker/web/html.py (53%)
mode change 100755 => 100644
copy x2gobroker/{__init__.py => web/json.py} (70%)
The diff of changes is:
diff --git a/etc/x2gobroker.conf b/etc/x2gobroker.conf
index 0123e60..ec6f4a9 100644
--- a/etc/x2gobroker.conf
+++ b/etc/x2gobroker.conf
@@ -63,8 +63,8 @@ use-authid = false
# below value to true
use-static-authid = true
-# Make up your own static_authid below...
-static-authid = <aaaavveeeerrrrryyyyylooonnnnggggssttrrriiinnnggg>
+# Make up your own authid below...
+authid = <aaaavveeeerrrrryyyyylooonnnnggggssttrrriiinnnggg>
# X2Go Session Broker knows about two output formats: a text/html based output
# and a text/json based output. The different outputs run under different URLs
diff --git a/sbin/x2gobroker b/sbin/x2gobroker
index 0b42c84..b5f3b48 100755
--- a/sbin/x2gobroker
+++ b/sbin/x2gobroker
@@ -23,132 +23,57 @@
import sys
import os
import web
+import argparse
try:
import x2gobroker
except ImportError:
sys.path.insert(0, os.path.join(os.getcwd(), '..'))
-# FIXME: here we have to add some code that genuinely detects the session broker backend...
-broker_backend = "zeroconf"
-
-# load the requested broker
-if broker_backend == "zeroconf":
- import x2gobroker.zeroconf as broker
-elif broker_backend == "simple":
- import x2gobroker.simple as broker
-elif broker_backend == "ldap":
- import x2gobroker.ldap as broker
-
-
-urls = ( '/', 'x2gobroker' )
-
-
-class x2gobroker:
-
- broker_backend = broker.X2GoBroker()
-
- http_header_items = {
- 'Content-Type': 'text/html; charset=utf-8',
- 'Expires': '+1h',
- }
-
- page = web.template.Template("""$def with (html_header_items, output)
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-<head>
-$for meta_tag in html_header_items["meta"]:
- <meta $meta_tag="$html_header_items["meta"][meta_tag]">
-<title>$html_header_items['title']</title>
-</head>
+# parse-in potential command line options
+cmdline_args = None
+if __name__ == "__main__":
+ import setproctitle
+ setproctitle.setproctitle(os.path.basename(sys.argv[0]))
-<body>
-$output
-</body>
-</html>
-"""
- )
- html_header_items = {
- 'title': 'X2Go Session Broker',
- 'meta': {
- 'author': 'X2Go Developers <x2go-dev at lists.berlios.de>',
- 'charset': 'utf-8',
- 'keywords': 'X2Go',
- 'description': 'X2Go Session Broker',
- },
+ daemon_options = [
+ {'args':['-C','--config-file'], 'default': None, 'metavar': 'CONFIG_FILE', 'help': 'Specify a special configuration file name, default is: /etc/x2go/x2gobroker.conf', },
+ {'args':['-b', '--bind'], 'default': '127.0.0.1:8080', 'metavar': 'BIND_ADDRESS', 'help': 'The [address:]port that the web.py http-engine shall bind to (default: 127.0.0.1:8080)', },
+ ]
+ p = argparse.ArgumentParser(description='X2Go Session Broker (Standalone Daemon)',\
+ formatter_class=argparse.RawDescriptionHelpFormatter, \
+ add_help=True, argument_default=None)
+ p_daemon = p.add_argument_group('standalone-daemon arguments')
+
+ for (p_group, opts) in ( (p_daemon, daemon_options), ):
+ for opt in opts:
+ args = opt['args']
+ del opt['args']
+ p_group.add_argument(*args, **opt)
+
+ cmdline_args = p.parse_args()
+
+ ### FIXME: not working yet for the config_file diversion via -C option
+ broker_kwargs = {
+ 'config_file': cmdline_args.config_file,
}
- def _gen_http_header(self):
-
- for http_header_item in self.http_header_items.keys():
- web.header(http_header_item, self.http_header_items[http_header_item])
-
- def GET(self):
-
- data = web.input()
- output = ''
-
- self._gen_http_header()
-
-
- # FIXME: the ,,testcon'' task can be object to DoS attacks...
- if hasattr(data, 'task') and data.task == 'testcon':
-
- ###
- ### TEST THE CONNECTION
- ###
-
- return self.broker_backend.test_connection()
-
- if hasattr(data, 'user') and hasattr(data, 'password') and self.broker_backend.check_access(username=data.user, password=data.password):
-
- ###
- ### PERFORM INITIAL AUTHENTICATION
- ###
-
- output += "<strong>Access granted</strong><br />"
- output += "AUTHID: {authid}<br />".format(authid=self.broker_backend.get_next_authid(username=data.user))
- return self.page(self.html_header_items, output)
-
- else:
- return self.page(self.html_header_items, "<hr>Access denied")
-
- if hasattr(data, 'user') and hasattr(data, 'authid'):
-
- ###
- ### X2GO BROKER TASKS
- ###
-
- if self.broker_backend.check_access(username=data.user, authid=data.authid):
-
- if hasattr(data, 'task'):
- task = data.task
-
- if task == 'listsessions':
-
- output += self.broker_backend.list_sessions()
-
- if task == 'selectsession':
-
- if hasattr(data, 'sid'):
-
- output += self.broker_backend.select_session(session_name=data.sid)
-
- if task == 'setpass':
-
- if hasattr(data, 'oldpass') and hasattr(data, 'newpass'):
-
- output += self.broker_backend.change_password(new=data.newpass, old=data.oldpass)
-
- return self.page(self.html_header_items, output)
-
- else:
- return self.page(self.html_header_items, "<hr>Access denied")
+# import classes serving the different web.py URLs
+from x2gobroker.web.html import *
+#from x2gobroker.web.json import *
+# define the web.py URLs
+urls = ( '/html/(.*)', 'X2GoBrokerWebHtml',
+# '/json/(.*)', 'X2GoBrokerWebJson',
+ )
+# run the web.py standalone daemon...
if __name__ == "__main__":
- import setproctitle
- setproctitle.setproctitle(os.path.basename(sys.argv[0]))
+ if len(sys.argv) <= 1:
+ sys.argv.append('')
+ sys.argv.append('')
+ sys.argv[1] = cmdline_args.bind
+ sys.argv[2:] = []
app = web.application(urls, globals())
app.internalerror = web.debugerror
app.run()
diff --git a/x2gobroker/__init__.py b/x2gobroker/backends/__init__.py
similarity index 97%
copy from x2gobroker/__init__.py
copy to x2gobroker/backends/__init__.py
index ad8c1e4..11b7f8f 100644
--- a/x2gobroker/__init__.py
+++ b/x2gobroker/backends/__init__.py
@@ -18,6 +18,3 @@
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-__VERSION__ = '0.0.0.1'
-
-
diff --git a/x2gobroker/base.py b/x2gobroker/backends/base.py
similarity index 61%
rename from x2gobroker/base.py
rename to x2gobroker/backends/base.py
index a1fe0ca..f5228f7 100644
--- a/x2gobroker/base.py
+++ b/x2gobroker/backends/base.py
@@ -28,6 +28,9 @@ __NAME__ = 'x2gobroker-pylib'
import types
import uuid
+# X2Go Broker modules
+import x2gobroker.config
+
class X2GoBroker(object):
"""\
X2GoBrokerBASE is an abstract class for X2Go broker implementations.
@@ -40,12 +43,16 @@ class X2GoBroker(object):
L{ldap.X2GoBroker}
"""
- def __init__(self):
+
+ def __init__(self, config_file="/etc/x2go/x2gobroker.conf"):
"""\
Initialize a new X2GoBroker instance to control X2Go session through an
X2Go Client with an intermediate session broker.
+
"""
- self._authid_dict = {}
+ self.config = x2gobroker.config.X2GoBrokerConfigFile()
+
+ self._dynamic_authid_map = {}
def __del__(self):
"""\
@@ -54,6 +61,29 @@ class X2GoBroker(object):
"""
pass
+ def get_global_config(self):
+ """\
+ Get the global section of the configuration file.
+
+ @return: all global configuration parameters
+ @rtype: C{dict}
+
+ """
+ return self.config.get_global_config()
+
+ def get_backend_config(self, backend='zeroconf'):
+ """\
+ Get the configuration section of a specific backend.
+
+ @param backend: the name of the backend
+ @type backend: C{str}
+
+ @return: all backend configuration parameters
+ @rtype: C{dict}
+
+ """
+ return self.config.get_backend_config(backend=backend)
+
def test_connection(self):
#if($cgi->param('task') eq 'testcon')
#{
@@ -66,7 +96,7 @@ class X2GoBroker(object):
#}
return 'OK'
- def check_access(self, username='', password='', authid=None):
+ def check_access(self, username='', password='', authid=None, ):
"""\
Check if a given user with a given password may gain access to the
X2Go session broker.
@@ -80,32 +110,44 @@ class X2GoBroker(object):
@rtype: C{bool}
"""
+ ### FOR INTRANET LOAD BALANCER WE MAY JUST ALLOW ACCESS TO EVERYONE
+ ### This is handled through the config file, normally /etc/x2go/x2gobroker.conf
- ### IMPLEMENT YOUR AUTHENTICATION LOGIC FIRST, then call base.X2GoBroker.check_access
- ### to finalize the authentication process.
+ if not self.config.get_value('global', 'check-credentials'):
+ return True
- # Before calling this code, you have to evaluate username and password.
- #
- # If the credentials (username, password) are considered as valid then
- # set authid to True.
- #
- # If credentials are invalid, set authid to None.
+ ### IMPLEMENT YOUR AUTHENTICATION LOGIC IN THE self._check_access(**kwargs) METHOD
+ ### when inheriting from the base.X2GoBroker class.
- if type(authid) is types.StringType:
- authid = unicode(authid)
+ access = False
+ access = self._check_access(username=username, password=password, authid=authid)
- if type(authid) is types.UnicodeType:
+ # using authid as extra security?
+ if self.config.get_value('global', 'use-authid'):
- if authid == self._authid_dict[username]:
- self._authid_dict[username] = uuid.uuid5(namespace=authid, name=username)
- return True
+ if type(authid) is types.StringType:
+ authid = unicode(authid)
- elif type(authid) is types.BooleanType and authid is True:
- # generate a first uuid, initialize the connection
- self._authid_dict[username] = uuid.uuid4()
- return True
+ if self.config.get_value('global', 'use-static-authid'):
- return False
+ # evaluate access based on static authentication ID feature
+ access = access and ( authid == self.config.get_value('global', 'authid') )
+
+ else:
+
+ # evaluate access based on dynamic authentication ID feature
+ if self._dynamic_authid_map.has_key(username):
+ access = access and ( authid == self._dynamic_authid_map[username] )
+ if access:
+ self._dynamic_authid_map[username] = uuid.uuid5(namespace=authid, name=username)
+
+ else:
+ access = access and ( authid == self.config.get_value('global', 'authid') )
+ if access:
+ # generate a first uuid, initialize the dynamic authencation ID security feature
+ self._dynamic_authid_map[username] = uuid.uuid4()
+
+ return access
def get_next_authid(self, username):
"""\
@@ -119,7 +161,7 @@ class X2GoBroker(object):
"""
try:
- return self._authid_dict[username]
+ return self._dynamic_authid_map[username]
except KeyError:
return None
diff --git a/x2gobroker/ldap.py b/x2gobroker/backends/ldap.py
similarity index 100%
rename from x2gobroker/ldap.py
rename to x2gobroker/backends/ldap.py
diff --git a/x2gobroker/simple.py b/x2gobroker/backends/simple.py
similarity index 71%
rename from x2gobroker/simple.py
rename to x2gobroker/backends/simple.py
index ea3fc87..923676e 100644
--- a/x2gobroker/simple.py
+++ b/x2gobroker/backends/simple.py
@@ -25,21 +25,21 @@ X2goBrokerSIMPLE class - a simple X2GoBroker implementations that uses text-base
__NAME__ = 'x2gobroker-pylib'
# modules
+import pam
+
+# Python X2GoBroker modules
import x2gobroker.base
class X2GoBroker(x2gobroker.base.X2GoBroker):
"""\
"""
- def __init__(self):
- """\
-
- """
- x2gobroker.base.X2GoBroker.__init__(self)
-
- def __del__(self):
- """\
+ def check_access(self, username='', password='', authid=None):
- """
- x2gobroker.base.X2GoBroker.__del__(self)
+ # do a simple PAM authentication against the PAM service ,,x2gobroker''
+ if username and password:
+ if pam.authenticate(username, password, service="x2gobroker"):
+ return True
+ return False
+ return x2gobroker.base.X2GoBroker.check_access(self, username=username, password=password, authid=authid)
diff --git a/x2gobroker/zeroconf.py b/x2gobroker/backends/zeroconf.py
similarity index 77%
rename from x2gobroker/zeroconf.py
rename to x2gobroker/backends/zeroconf.py
index af0da2d..3598e68 100644
--- a/x2gobroker/zeroconf.py
+++ b/x2gobroker/backends/zeroconf.py
@@ -28,23 +28,19 @@ __NAME__ = 'x2gobroker-pylib'
import pam
import subprocess
-import x2gobroker.base
+import base
from x2gobroker.defaults import X2GOBROKER_AGENT_CMD as _X2GOBROKER_AGENT_CMD
-class X2GoBroker(x2gobroker.base.X2GoBroker):
+class X2GoBroker(base.X2GoBroker):
- def check_access(self, username='', password='', authid=None):
+ def _check_access(self, username='', password='', authid=None):
# do a simple PAM authentication against the PAM service ,,x2gobroker''
- if authid is None:
- if username and password:
- if pam.authenticate(username, password, service="x2gobroker"):
- authid = True
- else:
- authid = None
-
- return x2gobroker.base.X2GoBroker.check_access(self, username=username, password=password, authid=authid)
+ if username and password:
+ if pam.authenticate(username, password, service="x2gobroker"):
+ return True
+ return False
def list_sessions(self, username):
diff --git a/x2gobroker/config.py b/x2gobroker/config.py
new file mode 100644
index 0000000..99531ae
--- /dev/null
+++ b/x2gobroker/config.py
@@ -0,0 +1,308 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010-2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
+#
+# X2Go Session Broker is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# X2Go Session Broker 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# This code was initially written by for the Python X2Go project:
+# 2010 Dick Kniep <dick.kniep at lindix.nl>
+#
+
+"""\
+X2goProcessIniFile - helper class for parsing .ini files
+
+"""
+__NAME__ = 'x2goinifiles-pylib'
+
+# modules
+import os
+import ConfigParser
+import types
+import cStringIO
+
+# Python X2GoBroker modules
+import x2gobroker.utils
+
+from x2gobroker.defaults import X2GOBROKER_HOME as _X2GOBROKER_HOME
+from x2gobroker.defaults import X2GOBROKER_CONFIG_DEFAULTS as _X2GOBROKER_CONFIG_DEFAULTS
+
+class X2GoBrokerConfigFile(object):
+ """
+ Class for processing a ini-file like configuration file.
+
+ If entries are omitted in such a config file, they are filled with
+ default values (as hard-coded in Python X2goBroker), so the resulting objects
+ always contain the same fields.
+
+ The default values are also used to define a data type for each configuration
+ option. An on-the-fly type conversion takes place when loading the configuration
+ file.
+
+ """
+ defaultValues = {
+ 'none': {
+ 'none': 'empty',
+ },
+ }
+ write_user_config = False
+ user_config_file = None
+
+ def __init__(self, config_files='/etc/x2go/x2gobroker.conf', defaults=None):
+ """\
+ @param config_files: a list of configuration file names (e.g. a global filename and a user's home
+ directory filename)
+ @type config_files: C{list}
+ @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override
+ Python X2goBroker's hard-coded defaults in L{defaults}
+ @type defaults: C{dict}
+
+ """
+ # make sure a None type gets turned into list type
+ if not config_files:
+ config_files = []
+
+ # allow string/unicode objects as config_files, as well
+ if type(config_files) in (types.StringType, types.UnicodeType):
+ config_files = [config_files]
+ self.config_files = config_files
+
+ if x2gobroker.utils._checkConfigFileDefaults(defaults):
+ self.defaultValues = defaults
+ else:
+ self.defaultValues = _X2GOBROKER_CONFIG_DEFAULTS
+
+ # we purposefully do not inherit the ConfigParser class
+ # here as we do not want to run into name conflicts between
+ # X2GoBroker config file options and method / property names in
+ # SafeConfigParser... This is a pre-cautious approach...
+ self.iniConfig = ConfigParser.ConfigParser(self.defaultValues)
+ self.iniConfig.optionxform = str
+
+ _create_file = False
+ for file_name in self.config_files:
+ if file_name.startswith(_X2GOBROKER_HOME):
+ if not os.path.exists(file_name):
+ x2gobroker.utils.touch_file(file_name)
+ _create_file = True
+ break
+
+ self.load()
+
+ if _create_file:
+ self.write_user_config = True
+ self.write()
+
+ def __repr__(self):
+ result = 'X2goConfigFile('
+ for p in dir(self):
+ if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
+ result += p + '=' + str(self.__dict__[p]) + ','
+ result = result.strip(',')
+ return result + ')'
+
+ def load(self):
+ """\
+ R(e-r)ead configuration file(s).
+
+ """
+ _found_config_files = self.iniConfig.read(self.config_files)
+
+ for file_name in _found_config_files:
+ if file_name.startswith(os.path.normpath(_X2GOBROKER_HOME)):
+ # we will use the first file found in the user's home dir for writing modifications
+ self.user_config_file = file_name
+ break
+
+ self.config_files = _found_config_files
+ self._fill_defaults()
+
+ def _storeValue(self, section, key, value):
+ """\
+ Stores a value for a given section and key.
+
+ This methods affects a SafeConfigParser object held in
+ RAM. No configuration file is affected by this
+ method. To write the configuration to disk use
+ the L{write()} method.
+
+ @param section: the ini file section
+ @type section: C{str}
+ @param key: the ini file key in the given section
+ @type key: C{str}
+ @param value: the value for the given section and key
+ @type value: C{str}, C{list}, C{booAl}, ...
+
+ """
+ if type(value) == type(u''):
+ value = value.encode(x2gobroker.utils.get_encoding())
+ if type(value) is types.BooleanType:
+ self.iniConfig.set(section, key, str(int(value)))
+ elif type(value) in (types.ListType, types.TupleType):
+ self.iniConfig.set(section, key, ", ".join(value))
+ else:
+ self.iniConfig.set(section, key, str(value))
+
+ def _fill_defaults(self):
+ """\
+ Fills a C{SafeConfigParser} object with the default config file
+ values as pre-defined in Python X2GoBroker or. This SafeConfigParser
+ object is held in RAM. No configuration file is affected by this
+ method.
+
+ """
+ for section, sectionvalue in self.defaultValues.items():
+ for key, value in sectionvalue.items():
+ if self.iniConfig.has_option(section, key): continue
+ if not self.iniConfig.has_section(section):
+ self.iniConfig.add_section(section)
+ self._storeValue(section, key, value)
+
+ def update_value(self, section, key, value):
+ """\
+ Change a value for a given section and key. This method
+ does not have any effect on configuration files.
+
+ @param section: the ini file section
+ @type section: C{str}
+ @param key: the ini file key in the given section
+ @type key: C{str}
+ @param value: the value for the given section and key
+ @type value: C{str}, C{list}, C{bool}, ...
+
+ """
+ if not self.iniConfig.has_section(section):
+ self.iniConfig.add_section(section)
+ self._storeValue(section, key, value)
+ self.write_user_config = True
+
+ def write(self):
+ """\
+ Write the ini file modifications (SafeConfigParser object) from RAM to disk.
+
+ For writing the first of the C{config_files} specified on instance construction
+ that is writable will be used.
+
+ """
+ if self.user_config_file and self.write_user_config:
+ fd = open(self.user_config_file, 'wb')
+ self.iniConfig.write(fd)
+ fd.close()
+ self.write_user_config = False
+
+ def get_type(self, section, key):
+ """\
+ Retrieve a value type for a given section and key. The returned
+ value type is based on the default values dictionary.
+
+ @param section: the ini file section
+ @type section: C{str}
+ @param key: the ini file key in the given section
+ @type key: C{str}
+
+ @return: a Python variable type
+ @rtype: class
+
+ """
+ return type(self.defaultValues[section][key])
+
+ def get_value(self, section, key, key_type=None):
+ """\
+ Retrieve a value for a given section and key.
+
+ @param section: the ini file section
+ @type section: C{str}
+ @param key: the ini file key in the given section
+ @type key: C{str}
+
+ @return: the value for the given section and key
+ @rtype: class
+
+ """
+ if key_type is None:
+ key_type = self.get_type(section, key)
+ if self.iniConfig.has_option(section, key):
+ if key_type is types.BooleanType:
+ return self.iniConfig.getboolean(section, key)
+ elif key_type is types.IntType:
+ return self.iniConfig.getint(section, key)
+ elif key_type is types.ListType:
+ _val = self.iniConfig.get(section, key)
+ _val = _val.strip()
+ if _val.startswith('[') and _val.endswith(']'):
+ return eval(_val)
+ elif ',' in _val:
+ _val = [ v.strip() for v in _val.split(',') ]
+ else:
+ _val = [ _val ]
+ return _val
+ else:
+ _val = self.iniConfig.get(section, key)
+ return _val.decode(x2gobroker.utils.get_encoding())
+ get = get_value
+ __call__ = get_value
+
+ def get_section(self, section):
+ """\
+ Get all keys and values for a certain section of the config file.
+
+ @param section: the name of the section to get
+ @type section: C{str}
+
+ @return: the section with all keys and values
+ @rtype: C{dict}
+
+ """
+ _section_config = {}
+ for option in self.iniConfig.options(section):
+ if option not in self.iniConfig.sections():
+ _section_config[option] = self.get(section, option, key_type=self.get_type(section, option))
+
+ return _section_config
+
+ def get_global_config(self):
+ """\
+ Get the global section of the configuration file.
+
+ @return: all global configuration parameters
+ @rtype: C{dict}
+
+ """
+ return self.get_section('global')
+
+ def get_backend_config(self, backend='zeroconf'):
+ """\
+ Get the configuration section of a specific backend.
+
+ @param backend: the name of the backend
+ @type backend: C{str}
+
+ @return: all backend configuration parameters
+ @rtype: C{dict}
+
+ """
+ return self.get_section(backend)
+
+ @property
+ def printable_config_file(self):
+ """\
+ Returns a printable configuration file as a multi-line string.
+
+ """
+ stdout = cStringIO.StringIO()
+ self.iniConfig.write(stdout)
+ _ret_val = stdout.getvalue()
+ stdout.close()
+ return _ret_val
diff --git a/x2gobroker/defaults.py b/x2gobroker/defaults.py
index d3de516..b9dc3c6 100644
--- a/x2gobroker/defaults.py
+++ b/x2gobroker/defaults.py
@@ -19,8 +19,13 @@
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+# modules
+import os
import uuid
+# the home directory of the user that the daemon/cgi runs as
+X2GOBROKER_HOME = os.path.normpath(os.path.expanduser('~'))
+
# FIXME: this path must not be hard-coded
X2GOBROKER_AGENT_CMD="/usr/lib/x2gobroker-agent"
@@ -30,14 +35,14 @@ X2GOBROKER_CONFIG_DEFAULTS = {
'backend': 'zeroconf',
'check-credentials': True,
'use-authid': False,
- 'use-static-authid': true,
- 'static-authid': uuid.uuid4(),
+ 'use-static-authid': True,
+ 'authid': uuid.uuid4(),
'enable-html-output': True,
'enable-json-output': False,
},
'zeroconf': {
'enable': True,
- }
+ },
'simple': {
'enable': False,
'session-profiles': '/etc/x2go/x2gobroker-simple-sessionprofiles.conf',
@@ -48,7 +53,7 @@ X2GOBROKER_CONFIG_DEFAULTS = {
'session-profiles': '/etc/x2go/x2gobroker-loadbalancer-sessionprofiles.conf',
'server-list-PROFILENAME1': ['server1.profile1.mydomain.tld','server2.profile1.mydomain.tld','server3.profile1.mydomain.tld',],
'server-list-PROFILENAME2': ['server1.profile2.mydomain.tld','server2.profile2.mydomain.tld',],
- }
+ },
'ldap': {
'enable': False,
'uri': 'ldap://localhost:389',
diff --git a/x2gobroker/utils.py b/x2gobroker/utils.py
new file mode 100644
index 0000000..1a74ed8
--- /dev/null
+++ b/x2gobroker/utils.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
+# Copyright (C) 2012 by Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
+# Copyright (C) 2012 by Heinz-Markus Graesing <heinz-m.graesing at obviously-nice.de>
+#
+# X2Go Session Broker is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# X2Go Session Broker 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import os
+import sys
+import types
+import locale
+
+def _checkConfigFileDefaults(data_structure):
+ """\
+ Check an ini-file-like data structure.
+
+ @param data_structure: an ini-file-like data structure
+ @type data_structure: C{dict} of C{dict}s
+
+ @return: C{True} if C{data_structure} matches that of an ini file data structure
+ @rtype: C{bool}
+
+ """
+ if data_structure is None:
+ return False
+ if type(data_structure) is not types.DictType:
+ return False
+ for sub_dict in data_structure.values():
+ if type(sub_dict) is not types.DictType:
+ return False
+ return True
+
+
+def touch_file(filename, mode='a'):
+ """\
+ Imitates the behaviour of the GNU/touch command.
+
+ @param filename: name of the file to touch
+ @type filename: C{str}
+ @param mode: the file mode (as used for Python file objects)
+ @type mode: C{str}
+
+ """
+ if not os.path.isdir(os.path.dirname(filename)):
+ os.makedirs(os.path.dirname(filename), mode=00700)
+ f = open(filename, mode=mode)
+ f.close()
+
+
+def get_encoding():
+ """\
+ Detect systems default character encoding.
+
+ @return: The system's local character encoding.
+ @rtype: C{str}
+
+ """
+ try:
+ encoding = locale.getdefaultlocale()[1]
+ if encoding is None:
+ raise BaseException
+ except:
+ try:
+ encoding = sys.getdefaultencoding()
+ except:
+ encoding = 'ascii'
+ return encoding
+
diff --git a/x2gobroker/__init__.py b/x2gobroker/web/__init__.py
similarity index 97%
copy from x2gobroker/__init__.py
copy to x2gobroker/web/__init__.py
index ad8c1e4..11b7f8f 100644
--- a/x2gobroker/__init__.py
+++ b/x2gobroker/web/__init__.py
@@ -18,6 +18,3 @@
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-__VERSION__ = '0.0.0.1'
-
-
diff --git a/sbin/x2gobroker b/x2gobroker/web/html.py
old mode 100755
new mode 100644
similarity index 53%
copy from sbin/x2gobroker
copy to x2gobroker/web/html.py
index 0b42c84..f83bc1b
--- a/sbin/x2gobroker
+++ b/x2gobroker/web/html.py
@@ -20,33 +20,10 @@
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-import sys
-import os
+# modules
import web
-try:
- import x2gobroker
-except ImportError:
- sys.path.insert(0, os.path.join(os.getcwd(), '..'))
-
-# FIXME: here we have to add some code that genuinely detects the session broker backend...
-broker_backend = "zeroconf"
-
-# load the requested broker
-if broker_backend == "zeroconf":
- import x2gobroker.zeroconf as broker
-elif broker_backend == "simple":
- import x2gobroker.simple as broker
-elif broker_backend == "ldap":
- import x2gobroker.ldap as broker
-
-
-urls = ( '/', 'x2gobroker' )
-
-
-class x2gobroker:
-
- broker_backend = broker.X2GoBroker()
+class X2GoBrokerWebHtml:
http_header_items = {
'Content-Type': 'text/html; charset=utf-8',
@@ -83,72 +60,86 @@ $output
for http_header_item in self.http_header_items.keys():
web.header(http_header_item, self.http_header_items[http_header_item])
- def GET(self):
+ def GET(self, backend):
+
+ if not backend:
+ backend = 'zeroconf'
+ else:
+ backend = backend.rstrip('/')
+
+ # silence pyflakes...
+ broker_backend = None
+ exec("import x2gobroker.backends.{backend}".format(backend=backend))
+ exec("broker_backend = x2gobroker.backends.{backend}.X2GoBroker()".format(backend=backend))
+ global_config = broker_backend.get_global_config()
+ backend_config = broker_backend.get_backend_config(backend)
data = web.input()
+ try: username = data.user
+ except AttributeError: username = ''
+ try: password = data.password
+ except AttributeError: password = ''
+ try: authid = data.authid
+ except AttributeError: authid = ''
+ try: task = data.task
+ except AttributeError: task = ''
+ try: session_name = data.sid
+ except AttributeError: session_name = ''
+ try: new_password = data.newpass
+ except AttributeError: new_password = ''
+
output = ''
self._gen_http_header()
-
# FIXME: the ,,testcon'' task can be object to DoS attacks...
- if hasattr(data, 'task') and data.task == 'testcon':
+ if task == 'testcon':
###
### TEST THE CONNECTION
###
- return self.broker_backend.test_connection()
+ return broker_backend.test_connection()
- if hasattr(data, 'user') and hasattr(data, 'password') and self.broker_backend.check_access(username=data.user, password=data.password):
+ if broker_backend.check_access(username=username, password=password, authid=authid):
- ###
- ### PERFORM INITIAL AUTHENTICATION
- ###
+ if not task:
+ ###
+ ### PERFORM A TEST AUTHENTICATION
+ ###
- output += "<strong>Access granted</strong><br />"
- output += "AUTHID: {authid}<br />".format(authid=self.broker_backend.get_next_authid(username=data.user))
- return self.page(self.html_header_items, output)
+ if global_config['use-authid']:
- else:
- return self.page(self.html_header_items, "<hr>Access denied")
-
- if hasattr(data, 'user') and hasattr(data, 'authid'):
-
- ###
- ### X2GO BROKER TASKS
- ###
-
- if self.broker_backend.check_access(username=data.user, authid=data.authid):
+ ### FIXME: make up a nice protocol for this, disabled for now
+ #output += "AUTHID: {authid}<br />".format(authid=broker_backend.get_next_authid(username=data.user))
+ pass
- if hasattr(data, 'task'):
- task = data.task
+ output += "<strong>Access granted</strong><br />"
+ return self.page(self.html_header_items, output)
- if task == 'listsessions':
+ else:
- output += self.broker_backend.list_sessions()
+ ###
+ ### X2GO BROKER TASKS
+ ###
- if task == 'selectsession':
+ if task == 'listsessions':
- if hasattr(data, 'sid'):
+ output += broker_backend.list_sessions()
- output += self.broker_backend.select_session(session_name=data.sid)
+ if task == 'selectsession':
- if task == 'setpass':
+ if session_name:
- if hasattr(data, 'oldpass') and hasattr(data, 'newpass'):
+ output += broker_backend.select_session(session_name=session_name)
- output += self.broker_backend.change_password(new=data.newpass, old=data.oldpass)
+ if task == 'setpass':
- return self.page(self.html_header_items, output)
+ if new_password:
- else:
- return self.page(self.html_header_items, "<hr>Access denied")
+ output += broker_backend.change_password(new_password=new_password)
+ return self.page(self.html_header_items, output)
-if __name__ == "__main__":
- import setproctitle
- setproctitle.setproctitle(os.path.basename(sys.argv[0]))
- app = web.application(urls, globals())
- app.internalerror = web.debugerror
- app.run()
+ else:
+ return self.page(self.html_header_items, "<hr>Access denied")
diff --git a/x2gobroker/__init__.py b/x2gobroker/web/json.py
similarity index 70%
copy from x2gobroker/__init__.py
copy to x2gobroker/web/json.py
index ad8c1e4..b879b77 100644
--- a/x2gobroker/__init__.py
+++ b/x2gobroker/web/json.py
@@ -1,7 +1,9 @@
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+# This file is part of the X2Go Project - http://www.x2go.org
+# Copyright (C) 2011-2012 by Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
+# Copyright (C) 2011-2012 by Heinz-Markus Graesing <heinz-m.graesing at obviously-nice.de>
# Copyright (C) 2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
-# Copyright (C) 2012 by Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
#
# X2Go Session Broker is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@@ -18,6 +20,10 @@
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-__VERSION__ = '0.0.0.1'
+# modules
+import web
+class X2GoBrokerWebJson:
+ # MUSIC OF THE FUTURE
+ pass
\ No newline at end of file
hooks/post-receive
--
x2gobroker.git (HTTP(S) Session broker for X2Go)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "x2gobroker.git" (HTTP(S) Session broker for X2Go).
More information about the x2go-commits
mailing list