Preliminary rpc proxy (outlook anywhere implementation):
authorJulien Kerihuel <j.kerihuel@openchange.org>
Tue, 15 May 2012 16:14:23 +0000 (16:14 +0000)
committerJulien Kerihuel <j.kerihuel@openchange.org>
Tue, 15 May 2012 16:14:23 +0000 (16:14 +0000)
- config parameters from ocsmanager.ini
- answer to rpc_in_data and rpc_out_data requests
- authenticate the user with basic auth vs samba4 AD

mapiproxy/services/ocsmanager/ocsmanager.ini
mapiproxy/services/ocsmanager/ocsmanager/config/routing.py
mapiproxy/services/ocsmanager/ocsmanager/controllers/rpcproxy.py [new file with mode: 0644]
mapiproxy/services/ocsmanager/ocsmanager/lib/config.py
mapiproxy/services/ocsmanager/ocsmanager/model/RPCProxyAuthenticateModel.py [new file with mode: 0644]
mapiproxy/services/ocsmanager/ocsmanager/tests/functional/test_rpcproxy.py [new file with mode: 0644]

index 44c2daeb8dbb6f61d32b2ebad13f14020597ebc2..13c1bad4c7a9dfded63956506f085e53f39e0381 100644 (file)
@@ -12,8 +12,8 @@ debug = yes
 #file = 
 
 [auth:ldap]
-host = ldap://xxx
-port = 489
+host = localhost
+port = 389
 bind_dn =
 bind_pw =
 basedn = 
@@ -24,3 +24,8 @@ basedn =
 username = openchange 
 # password is test
 password = {SSHA}I6Hy5Wv0wuxyXvMBFWFQDVVN12_CLaX9
+
+[rpcproxy:ldap]
+host = localhost
+port = 389
+basedn = CN=Users,DC=sambaxp,DC=local
\ No newline at end of file
index aa9d5764bcf9d9dd01cb8072e06eb5244310129a..5525b430ef2b73c428b19a047e6b6001f4162a94 100644 (file)
@@ -26,4 +26,7 @@ def make_map(config):
     map.connect('/{controller}/{action}')
     map.connect('/{controller}/{action}/{id}')
 
+    # RPC over HTTP
+    map.connect('/rpc/rpcproxy.dll', controller='rpcproxy')
+
     return map
diff --git a/mapiproxy/services/ocsmanager/ocsmanager/controllers/rpcproxy.py b/mapiproxy/services/ocsmanager/ocsmanager/controllers/rpcproxy.py
new file mode 100644 (file)
index 0000000..137f447
--- /dev/null
@@ -0,0 +1,32 @@
+import logging
+
+from pylons import request, response, session, tmpl_context as c, url
+from pylons.controllers.util import abort, redirect
+from ocsmanager.model import RPCProxyAuthenticateModel
+
+from ocsmanager.lib.base import BaseController, render
+
+log = logging.getLogger(__name__)
+
+class RpcproxyController(BaseController):
+
+    def index(self):
+        auth = RPCProxyAuthenticateModel.RPCProxyAuthenticateModel()
+        if request.method == 'RPC_IN_DATA':
+            log.debug('IN Channel Request')
+            # Check credentials
+            retval = auth.Authenticate(request.authorization)
+            response.headers['Content-Type'] = 'application/rpc'
+            if retval == 1:
+                log.debug('Authentication failure')
+            return
+        elif request.method == 'RPC_OUT_DATA':
+            log.debug('OUT Channel Request')
+            retval = auth.Authenticate(request.authorization)
+            response.headers['Content-Type'] = 'application/rpc'
+
+            if retval == 1:
+                log.debug('Authentication failure')
+
+        return ''
+
index 0ac497c7e02bcc66ff5ca3be411f583c0d264479..f8d6457ca450814f51ded8941dedba20e031f797 100644 (file)
@@ -89,6 +89,12 @@ class OCSConfig(object):
             self.__get_option(section, 'filter', 'auth', None, '(cn=%s)')
             self.__get_option(section, 'attrs', 'auth', None, '*')
 
+    def __parse_rpcproxy(self):
+        self.__get_section('rpcproxy:ldap')
+        self.__get_option('rpcproxy:ldap', 'host', 'rpcproxy', 'ldap_host')
+        self.__get_option('rpcproxy:ldap', 'port', 'rpcproxy', 'ldap_port')
+        self.__get_option('rpcproxy:ldap', 'basedn', 'rpcproxy', 'ldap_basedn')
+
     def load(self):
         """Load the configuration file.
         """
@@ -109,5 +115,6 @@ class OCSConfig(object):
 
         self.__parse_main()
         self.__parse_auth()
+        self.__parse_rpcproxy()
         
         return self.d
diff --git a/mapiproxy/services/ocsmanager/ocsmanager/model/RPCProxyAuthenticateModel.py b/mapiproxy/services/ocsmanager/ocsmanager/model/RPCProxyAuthenticateModel.py
new file mode 100644 (file)
index 0000000..3d82073
--- /dev/null
@@ -0,0 +1,64 @@
+import ldap
+import logging
+from pylons import config
+
+from base64 import urlsafe_b64encode as encode
+from base64 import urlsafe_b64decode as decode
+
+log = logging.getLogger(__name__)
+
+class RPCProxyAuthenticateModel:
+
+    def __init__(self):
+        self.basic = {}
+        self.basic["username"] = None
+        self.basic["password"] = None
+        self.ntlmssp = None
+        self.auth_type = None
+        self.ldap = {}
+        self.ldap['host'] = config['ocsmanager']['rpcproxy']['ldap_host']
+        self.ldap['post'] = config['ocsmanager']['rpcproxy']['ldap_port']
+        self.ldap['basedn'] = config['ocsmanager']['rpcproxy']['ldap_basedn']
+
+        return
+
+    def Authenticate(self, auth):
+        """ Authenticate user depending on the authentication type.
+        Return 0 on success otherwise 1.
+        """
+        if auth is None or len(auth) != 2:
+            return 1
+
+        if auth[0] == 'Basic':
+            return self.AuthenticateBasic(auth[1])
+        elif auth[0] == 'NTLM':
+            return self.AuthenticateNTLM(auth[1])
+        else:
+            return 1
+
+    def AuthenticateBasic(self, payload):
+        """ Implement Basic authentication scheme support.
+        """
+        blob = decode(payload)
+        credentials = blob.split(':')
+        if len(credentials[0].split('\\')) == 2:
+            username = credentials[0].split('\\')[1]
+        else:
+            username = credentials[0]
+        
+        try:
+            l = ldap.open(self.ldap['host'])
+            l.protocol_version = ldap.VERSION3
+            username = 'CN=%s,%s' % (username, self.ldap['basedn'])
+            password = credentials[1]
+            l.simple_bind(username, password)
+        except ldap.LDAPError, e:
+            log.debug(e)
+            return 1
+
+        return 0
+
+    def AuthenticateNTLM(self, payload):
+        """ Implement NTLM authentication scheme support.
+        """
+        return 1
diff --git a/mapiproxy/services/ocsmanager/ocsmanager/tests/functional/test_rpcproxy.py b/mapiproxy/services/ocsmanager/ocsmanager/tests/functional/test_rpcproxy.py
new file mode 100644 (file)
index 0000000..e92cb90
--- /dev/null
@@ -0,0 +1,7 @@
+from ocsmanager.tests import *
+
+class TestRpcproxyController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url(controller='rpcproxy', action='index'))
+        # Test response...