[CalendarServer-changes] [13694] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Jun 26 11:07:03 PDT 2014


Revision: 13694
          http://trac.calendarserver.org//changeset/13694
Author:   sagen at apple.com
Date:     2014-06-26 11:07:03 -0700 (Thu, 26 Jun 2014)
Log Message:
-----------
Reimplement OS X Server SACLs using cffi

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/provision/root.py
    CalendarServer/trunk/calendarserver/provision/test/test_root.py
    CalendarServer/trunk/setup.py

Added Paths:
-----------
    CalendarServer/trunk/calendarserver/platform/darwin/sacl.py

Removed Paths:
-------------
    CalendarServer/trunk/calendarserver/platform/darwin/_sacl.c

Deleted: CalendarServer/trunk/calendarserver/platform/darwin/_sacl.c
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/_sacl.c	2014-06-26 01:35:18 UTC (rev 13693)
+++ CalendarServer/trunk/calendarserver/platform/darwin/_sacl.c	2014-06-26 18:07:03 UTC (rev 13694)
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2006-2014 Apple Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Python.h"
-#include <Security/Security.h>
-#include <membership.h>
-
-int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember);
-int mbr_user_name_to_uuid(const char* name, uuid_t uu);
-int mbr_group_name_to_uuid(const char* name, uuid_t uu);
-
-/*
-    CheckSACL(userOrGroupName, service)
-    Checks user or group membership in a service.
-*/
-static PyObject *appleauth_CheckSACL(PyObject *self, PyObject *args) {
-    char *username;
-    int usernameSize;
-    char *serviceName;
-    int serviceNameSize;
-
-    char *prefix = "com.apple.access_";
-    char groupName[256];
-    uuid_t group_uu;
-
-    // get the args
-    if (!PyArg_ParseTuple(args, "s#s#", &username,
-                          &usernameSize, &serviceName, &serviceNameSize)) {
-        return NULL;
-    }
-
-    // If the username is empty, see if there is a com.apple.access_<service>
-    // group
-    if ( usernameSize == 0 ) {
-        if ( strlen(serviceName) > 255 - strlen(prefix) ) {
-            return Py_BuildValue("i", (-3));
-        }
-        memcpy(groupName, prefix, strlen(prefix));
-        strcpy(groupName + strlen(prefix), serviceName);
-        if ( mbr_group_name_to_uuid(groupName, group_uu) == 0 ) {
-            // com.apple.access_<serviceName> group does exist, so
-            // unauthenticated users are not allowed
-            return Py_BuildValue("i", (-1));
-        } else {
-            // com.apple.access_<serviceName> group doesn't exist, so
-            // unauthenticated users are allowed
-            return Py_BuildValue("i", 0);
-        }
-    }
-
-    // get a uuid for the user
-    uuid_t user;
-    int result = mbr_user_name_to_uuid(username, user);
-    int isMember = 0;
-
-    if ( result != 0 ) {
-        // no uuid for the user, we might be a group.
-        result = mbr_group_name_to_uuid(username, user);
-    }
-
-    if ( result != 0 ) {
-        return Py_BuildValue("i", (-1));
-    }
-
-    result = mbr_check_service_membership(user, serviceName, &isMember);
-
-    if ( ( result == 0 && isMember == 1 ) || ( result == ENOENT ) ) {
-        // passed
-        return Py_BuildValue("i", 0);
-    }
-
-    return Py_BuildValue("i", (-2));
-}
-
-/* Method definitions. */
-static struct PyMethodDef _sacl_methods[] = {
-    {"CheckSACL", appleauth_CheckSACL},
-    {NULL, NULL} /* Sentinel */
-};
-
-void init_sacl(void) {
-    Py_InitModule("_sacl", _sacl_methods);
-}

Added: CalendarServer/trunk/calendarserver/platform/darwin/sacl.py
===================================================================
--- CalendarServer/trunk/calendarserver/platform/darwin/sacl.py	                        (rev 0)
+++ CalendarServer/trunk/calendarserver/platform/darwin/sacl.py	2014-06-26 18:07:03 UTC (rev 13694)
@@ -0,0 +1,85 @@
+##
+# Copyright (c) 2005-2014 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from __future__ import print_function
+
+__all__ = [
+    "checkSACL"
+]
+
+from cffi import FFI, VerificationError
+
+ffi = FFI()
+
+definitions = """
+    typedef unsigned char uuid_t[16];
+    int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember);
+    int mbr_user_name_to_uuid(const char* name, uuid_t uu);
+    int mbr_group_name_to_uuid(const char* name, uuid_t uu);
+"""
+
+ffi.cdef(definitions)
+
+try:
+    lib = ffi.verify(definitions, libraries=[])
+except VerificationError as ve:
+    raise ImportError(ve)
+
+
+def checkSACL(userOrGroupName, serviceName):
+    """
+    Check to see if a given user or group is a member of an OS X Server
+    service's access group.  If userOrGroupName is an empty string, we
+    want to know if unauthenticated access is allowed for the given service.
+
+    @param userOrGroupName: the name of the user or group
+    @type userOrGroupName: C{unicode}
+
+    @param serviceName: the name of the service (e.g. calendar, addressbook)
+    @type serviceName: C{str}
+
+    @return: True if the user or group is allowed access to service
+    @rtype: C{bool}
+    """
+
+    userOrGroupName = userOrGroupName.encode("utf-8")
+    prefix = "com.apple.access_"
+    uu = ffi.new("uuid_t")
+
+    # See if the access group exists.  If it does not, then there are no
+    # restrictions
+    groupName = prefix + serviceName
+    groupMissing = lib.mbr_group_name_to_uuid(groupName, uu)
+    if groupMissing:
+        return True
+
+    # See if userOrGroupName matches a user
+    result = lib.mbr_user_name_to_uuid(userOrGroupName, uu)
+    if result:
+        # Not a user, try looking up a group of that name
+        result = lib.mbr_group_name_to_uuid(userOrGroupName, uu)
+
+    if result:
+        # Neither a user nor a group matches the name
+        return False
+
+    # See if the uuid is a member of the service access group
+    isMember = ffi.new("int *")
+    result = lib.mbr_check_service_membership(uu, serviceName, isMember)
+    if not result and isMember[0]:
+        return True
+
+    return False

Modified: CalendarServer/trunk/calendarserver/provision/root.py
===================================================================
--- CalendarServer/trunk/calendarserver/provision/root.py	2014-06-26 01:35:18 UTC (rev 13693)
+++ CalendarServer/trunk/calendarserver/provision/root.py	2014-06-26 18:07:03 UTC (rev 13694)
@@ -19,6 +19,12 @@
     "RootResource",
 ]
 
+try:
+    from calendarserver.platform.darwin.sacl import checkSACL
+except ImportError:
+    # OS X Server SACLs not supported on this system, make SACL check a no-op
+    checkSACL = lambda *ignored: True
+
 from twext.python.log import Logger
 from twisted.cred.error import LoginFailed, UnauthorizedLogin
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
@@ -75,10 +81,7 @@
         super(RootResource, self).__init__(path, *args, **kwargs)
 
         if config.EnableSACLs:
-            if RootResource.CheckSACL:
-                self.useSacls = True
-            else:
-                log.warn("SACLs are enabled, but SACLs are not supported.")
+            self.useSacls = True
 
         self.contentFilters = []
 
@@ -122,7 +125,7 @@
 
 
     @inlineCallbacks
-    def checkSacl(self, request):
+    def checkSACL(self, request):
         """
         Check SACLs against the current request
         """
@@ -147,7 +150,7 @@
         # with an empty string.
         if authzUser is None:
             for saclService in saclServices:
-                if RootResource.CheckSACL("", saclService) == 0:
+                if checkSACL("", saclService):
                     # No group actually exists for this SACL, so allow
                     # unauthenticated access
                     returnValue(True)
@@ -169,7 +172,7 @@
 
         access = False
         for saclService in saclServices:
-            if RootResource.CheckSACL(username, saclService) == 0:
+            if checkSACL(username, saclService):
                 # Access is allowed
                 access = True
                 break
@@ -346,7 +349,7 @@
             self.useSacls and
             not hasattr(request, "checkedSACL")
         ):
-            yield self.checkSacl(request)
+            yield self.checkSACL(request)
 
         if config.RejectClients:
             #
@@ -432,11 +435,3 @@
 
     def http_DELETE(self, request):
         return responsecode.FORBIDDEN
-
-# So CheckSACL will be parameterized
-# We do this after RootResource is defined
-try:
-    from calendarserver.platform.darwin._sacl import CheckSACL
-    RootResource.CheckSACL = CheckSACL
-except ImportError:
-    RootResource.CheckSACL = None

Modified: CalendarServer/trunk/calendarserver/provision/test/test_root.py
===================================================================
--- CalendarServer/trunk/calendarserver/provision/test/test_root.py	2014-06-26 01:35:18 UTC (rev 13693)
+++ CalendarServer/trunk/calendarserver/provision/test/test_root.py	2014-06-26 18:07:03 UTC (rev 13694)
@@ -26,22 +26,27 @@
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
 
-from calendarserver.provision.root import RootResource
+import calendarserver.provision.root  # for patching checkSACL
 
 
-class FakeCheckSACL(object):
-    def __init__(self, sacls=None):
-        self.sacls = sacls or {}
+TEST_SACLS = {
+    "calendar": [
+        "dreid"
+    ],
+    "addressbook": [
+        "dreid"
+    ],
+}
 
 
-    def __call__(self, username, service):
-        if service not in self.sacls:
-            return 1
+def stubCheckSACL(username, service):
+    if service not in TEST_SACLS:
+        return True
 
-        if username in self.sacls[service]:
-            return 0
+    if username in TEST_SACLS[service]:
+        return True
 
-        return 1
+    return False
 
 
 
@@ -51,7 +56,7 @@
     def setUp(self):
         yield super(RootTests, self).setUp()
 
-        RootResource.CheckSACL = FakeCheckSACL(sacls={"calendar": ["dreid"]})
+        self.patch(calendarserver.provision.root, "checkSACL", stubCheckSACL)
 
 
 
@@ -337,7 +342,7 @@
             "PROPFIND",
             "/principals/users/dreid/",
             headers=http_headers.Headers({
-                    'Depth': '1',
+                'Depth': '1',
             }),
             authPrincipal=principal,
             content=body
@@ -353,7 +358,7 @@
             "PROPFIND",
             "/principals/users/dreid/",
             headers=http_headers.Headers({
-                    'Depth': '1',
+                'Depth': '1',
             }),
             authPrincipal=principal,
             content=body

Modified: CalendarServer/trunk/setup.py
===================================================================
--- CalendarServer/trunk/setup.py	2014-06-26 01:35:18 UTC (rev 13693)
+++ CalendarServer/trunk/setup.py	2014-06-26 18:07:03 UTC (rev 13694)
@@ -256,17 +256,8 @@
 
 extensions = []
 
-# if sys.platform == "darwin":
-#     extensions.append(
-#         Extension(
-#             "calendarserver.platform.darwin._sacl",
-#             extra_link_args=["-framework", "Security"],
-#             sources=["calendarserver/platform/darwin/_sacl.c"]
-#         )
-#     )
 
 
-
 #
 # Run setup
 #
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140626/c0d941ca/attachment-0001.html>


More information about the calendarserver-changes mailing list