[X2Go-Commits] x2gobroker.git - tmp (branch) updated: 01ed711dba1fea373f1b212b40c1a50f61436ed4

X2Go dev team git-admin at x2go.org
Tue Apr 23 21:08:32 CEST 2013


The branch, tmp 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