[X2Go-Commits] x2gobroker.git - master (branch) updated: 0.0.1.0-44-ge1c9022

X2Go dev team git-admin at x2go.org
Fri Apr 26 00:53:18 CEST 2013


The branch, master has been updated
       via  e1c90224f4e364345e9e76aa3db086988e03a056 (commit)
      from  e6bbdb5bb97de5ee01cd9e659ba43f1dde5c7376 (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-wsgi.apache.conf   |    1 +
 etc/x2gobroker.conf               |    2 +
 x2gobroker/brokers/base_broker.py |    3 ++
 x2gobroker/defaults.py            |    1 +
 x2gobroker/uccsjson.py            |   30 ++++++-------
 x2gobroker/web/uccs.py            |   84 ++++++++++++++++++++++++++-----------
 6 files changed, 81 insertions(+), 40 deletions(-)

The diff of changes is:
diff --git a/etc/x2gobroker-wsgi.apache.conf b/etc/x2gobroker-wsgi.apache.conf
index 92c432f..63ba34a 100644
--- a/etc/x2gobroker-wsgi.apache.conf
+++ b/etc/x2gobroker-wsgi.apache.conf
@@ -5,6 +5,7 @@
 #X2GOBROKER_DAEMON_USER=x2gobroker
 #X2GOBROKER_DAEMON_GROUP=x2gobroker
 WSGIDaemonProcess x2gobroker user=x2gobroker group=x2gobroker processes=5 threads=15
+WSGIPassAuthorization On
 
 # default broker backend (default: zeroconf)
 SetEnv X2GOBROKER_DEFAULT_BACKEND zeroconf
diff --git a/etc/x2gobroker.conf b/etc/x2gobroker.conf
index 85eaa77..cf544bb 100644
--- a/etc/x2gobroker.conf
+++ b/etc/x2gobroker.conf
@@ -73,6 +73,8 @@
 
 # enable {base_url}/uccs/
 #enable-uccs-output = false
+# use this URL base to create URL field in UCCS-style JSON output
+#my-uccs-url-base = http://localhost:8080/
 
 # enable {base_url}/json/ (THIS IS FUTURE, mg-20121129)
 #enable-json-output = false
diff --git a/x2gobroker/brokers/base_broker.py b/x2gobroker/brokers/base_broker.py
index 76ed8ef..365ce0b 100644
--- a/x2gobroker/brokers/base_broker.py
+++ b/x2gobroker/brokers/base_broker.py
@@ -715,6 +715,9 @@ class X2GoBroker(object):
 
         access = False
         access = self._do_authenticate(username=username, password=password)
+        if not access and "@" in username:
+            _username = username.split('@')[0]
+            access = self._do_authenticate(username=_username, password=password)
         logger_broker.debug('base_broker.X2GoBroker.check_access(): result of authentication check is: {access}'.format(access=access))
 
         ### HANDLING OF DYNAMIC AUTHENTICATION ID HASHES
diff --git a/x2gobroker/defaults.py b/x2gobroker/defaults.py
index 7f1f3c8..d734cc6 100644
--- a/x2gobroker/defaults.py
+++ b/x2gobroker/defaults.py
@@ -119,6 +119,7 @@ X2GOBROKER_CONFIG_DEFAULTS = {
         u'my-cookie': uuid.uuid4(),
         u'enable-plain-output': True,
         u'enable-uccs-output': False,
+        u'my-uccs-url-base': 'http://localhost:8080/',
         u'enable-json-output': False,
         u'enable-html-output':  False,
         u'default-auth-mech': u'pam',
diff --git a/x2gobroker/uccsjson.py b/x2gobroker/uccsjson.py
index abbcd80..efbbc32 100644
--- a/x2gobroker/uccsjson.py
+++ b/x2gobroker/uccsjson.py
@@ -85,7 +85,7 @@ class ManagementServer():
         Dump this instance as JSON object.
 
         """
-        return json.dumps(self, default=convert_to_builtin_type)
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
 
 
 # NOT USED!!!
@@ -129,9 +129,9 @@ class RDPServer():
         @raise TypeError: domain has to be C{str} or C{unicode}
 
         """
-        if isinstance(domainName, str):
+        if isinstance(domain, str):
             self.WindowsDomain = unicode(domain)
-        elif isinstance(domainName, unicode):
+        elif isinstance(domain, unicode):
             self.WindowsDomain = domain
         else:
             raise TypeError("set_domain() expects a string or unicode argument")
@@ -141,7 +141,7 @@ class RDPServer():
         Dump this instance as JSON object.
 
         """
-        return json.dumps(self, default=convert_to_builtin_type)
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
 
 
 class ICAServer():
@@ -178,9 +178,9 @@ class ICAServer():
         @raise TypeError: domain has to be C{str} or C{unicode}
 
         """
-        if isinstance(domainName, str):
+        if isinstance(domain, str):
             self.WindowsDomain = unicode(domain)
-        elif isinstance(domainName, unicode):
+        elif isinstance(domain, unicode):
             self.WindowsDomain = domain
         else:
             raise TypeError("set_domain() expects a string or unicode argument")
@@ -190,7 +190,7 @@ class ICAServer():
         Dump this instance as JSON object.
 
         """
-        return json.dumps(self, default=convert_to_builtin_type)
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
 
 
 class X2GoServer():
@@ -210,12 +210,12 @@ class X2GoServer():
         @type password: C{unicode}
 
         """
-        self.URL = host
-        self.Name = name
-        self.Protocol = 'x2go'
+        self.URL = unicode(host)
+        self.Name = unicode(name)
+        self.Protocol = u'x2go'
         self.SessionTypeRequired = True
-        self.Username = username
-        self.Password = password
+        self.Username = unicode(username)
+        self.Password = unicode(password)
 
     def set_session_type(self, session_type):
         """\
@@ -227,8 +227,8 @@ class X2GoServer():
         @raise TypeError: session_type has to be C{str} or C{unicode}
 
         """
-        if isinstance(domainName, str):
-            self.SessionType = sessiontypeName
+        if isinstance(session_type, str):
+            self.SessionType = session_type
         else:
             raise TypeError("set_session_type() expects a string or unicode argument")
 
@@ -237,5 +237,5 @@ class X2GoServer():
         Dump this instance as JSON object.
 
         """
-        return json.dumps(self, default=convert_to_builtin_type)
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
 
diff --git a/x2gobroker/web/uccs.py b/x2gobroker/web/uccs.py
index a17b3b9..db59f24 100644
--- a/x2gobroker/web/uccs.py
+++ b/x2gobroker/web/uccs.py
@@ -22,6 +22,8 @@
 
 # modules
 import types
+import re
+import base64
 import tornado.web
 from tornado.escape import native_str, parse_qs_bytes
 
@@ -31,6 +33,45 @@ import x2gobroker.defaults
 from x2gobroker.loggers import logger_broker, logger_error
 import x2gobroker.uccsjson
 
+def require_basic_auth(realm, validate_callback):
+    def require_basic_auth_decorator(handler_class):
+        def wrap_execute(handler_execute):
+            def require_basic_auth(handler, kwargs):
+                def create_auth_header():
+                    handler.set_status(401)
+                    handler.set_header('WWW-Authenticate', 'Basic realm="{realm}"'.format(realm=realm))
+                    handler._transforms = []
+                    handler.finish()
+
+                auth_header = handler.request.headers.get('Authorization')
+                if auth_header is None or not auth_header.startswith('Basic '):
+                    create_auth_header()
+                else:
+                    auth_decoded = base64.decodestring(auth_header[6:])
+                    kwargs['basicauth_user'], kwargs['basicauth_pass'] = [ unicode(s) for s in auth_decoded.split(':', 2) ]
+                    if validate_callback(handler_class, kwargs['basicauth_user'], kwargs['basicauth_pass']):
+                        return True
+                    else:
+                        create_auth_header()
+            def _execute(self, transforms, *args, **kwargs):
+                if not require_basic_auth(self, kwargs):
+                    return False
+                return handler_execute(self, transforms, *args, **kwargs)
+            return _execute
+
+        handler_class._execute = wrap_execute(handler_class._execute)
+        return handler_class
+    return require_basic_auth_decorator
+
+
+def credentials_validate(handler_class, username, password):
+    import x2gobroker.brokers.base_broker
+    # FIXME: with the below hack, the backend broker detection in X2GoBrokerWeb is disabled, only global options
+    #        from x2gobroker.conf are available here...
+    return x2gobroker.brokers.base_broker.X2GoBroker().check_access(username=username, password=password)
+
+
+ at require_basic_auth('Authentication required', credentials_validate)
 class X2GoBrokerWeb(tornado.web.RequestHandler):
 
     http_header_items = {
@@ -43,69 +84,64 @@ class X2GoBrokerWeb(tornado.web.RequestHandler):
         for http_header_item in self.http_header_items.keys():
             self.set_header(http_header_item, self.http_header_items[http_header_item])
 
-    def get(self, backend):
+    def get(self, backend, basicauth_user, basicauth_pass):
         if x2gobroker.defaults.X2GOBROKER_DEBUG:
             self._gen_http_header()
             logger_broker.warn('GET http request detected, if unwanted: disable X2GOBROKER_DEBUG')
-            return self.head(backend)
+            return self.head(backend, basicauth_user, basicauth_pass)
         raise tornado.web.HTTPError(404)
 
-    def head(self, backend):
+    def head(self, backend, basicauth_user, basicauth_pass):
 
         if not backend:
             backend = x2gobroker.defaults.X2GOBROKER_DEFAULT_BACKEND
         else:
             backend = backend.rstrip('/')
 
-        # get the first and the third item as backend, api_version
-        backend, api_version = backend.split('/')[:3:2]
-
-        # silence pyflakes...
-        broker_backend = None
+        api_version = 4
+        if re.match('.*/api/[0-9].*', backend):
+            # get the first and the third item as backend, api_version
+            backend, api_version = backend.split('/')[:3:2]
+            api_version = int(api_version)
 
         try:
             # dynamically detect broker backend from given URL
             exec("import x2gobroker.brokers.{backend}_broker".format(backend=backend))
-            exec("broker_backend = x2gobroker.brokers.{backend}_broker.X2GoBroker()".format(backend=backend))
+            exec("self.broker_backend = x2gobroker.brokers.{backend}_broker.X2GoBroker()".format(backend=backend))
         except ImportError:
             # throw a 404 if the backend does not exist
             raise tornado.web.HTTPError(404)
 
-        global_config = broker_backend.get_global_config()
+        global_config = self.broker_backend.get_global_config()
 
         # if the broker backend is disabled in the configuration, pretend to have nothing on offer
-        if not broker_backend.is_enabled():
+        if not self.broker_backend.is_enabled():
             raise tornado.web.HTTPError(404)
 
         # set the client address for the broker backend
         ip = self.request.remote_ip
         if ip:
             logger_broker.info('client address is {address}'.format(address=ip))
-            broker_backend.set_client_address(ip)
+            self.broker_backend.set_client_address(ip)
         elif not x2gobroker.defaults.X2GOBROKER_DEBUG:
             # if the client IP is not set, we pretend to have nothing on offer
             logger_error.error('client could not provide an IP address, pretending: 404 Not Found')
             raise tornado.web.HTTPError(404)
 
-        username = 'foo'
-        #username = self.get_argument('user', default='')
-        #password = self.get_argument('password', default='')
-        #cookie = self.get_argument('cookie', default='')
-        #task = self.get_argument('task', default='')
-        #profile_id = self.get_argument('sid', default='')
-        #new_password = self.get_argument('newpass', default='')
+        username, password = basicauth_user, basicauth_pass
+        cookie = ''
 
         output = ''
 
-        #logger_broker.debug ('username: {username}, password: {password}, task: {task}, profile_id: {profile_id}'.format(username=username, password='XXXXX', task=task, profile_id=profile_id))
-        #if broker_backend.check_access(username=username, password=password, cookie=cookie):
+        logger_broker.debug ('Authenticated as username: {username}, with password: <hidden>'.format(username=username))
 
         ###
         ### CONFIRM SUCCESSFUL AUTHENTICATION FIRST
         ###
 
-        profiles = broker_backend.list_profiles(username)
-        ms = x2gobroker.uccsjson.ManagementServer('http://localhost:8080/uccs/{backend}'.format(backend=backend), 'X2Go Session Broker')
+        profiles = self.broker_backend.list_profiles(username)
+        urlbase = self.broker_backend.get_global_value('my-uccs-url-base').rstrip('/')
+        ms = x2gobroker.uccsjson.ManagementServer('{urlbase}/uccs/{backend}'.format(urlbase=urlbase, backend=backend), 'X2Go Session Broker')
 
         profile_ids = profiles.keys()
         profile_ids.sort()
@@ -127,5 +163,3 @@ class X2GoBrokerWeb(tornado.web.RequestHandler):
         self.write(output)
         return
 
-        #raise tornado.web.HTTPError(401)
-


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