Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing group restrictions #187

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions radicale/auth/PAM.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,44 @@ def is_authenticated(user, password):
GROUP_MEMBERSHIP)

return False


def is_in_group(user, group):
"""Check if the user is in the aforementioned group."""

# Check whether the user exists in the PAM system
try:
pwd.getpwnam(user).pw_uid
except KeyError:
log.LOGGER.debug("User %s not found" % user)
return False
else:
log.LOGGER.debug("User %s found" % user)

# Check whether the group exists
try:
# Obtain supplementary groups
members = grp.getgrnam(group).gr_mem
except KeyError:
log.LOGGER.debug(
"Group %s doesn't exist" %group)
return False

# Check whether the user exists
try:
# Get user primary group
primary_group = grp.getgrgid(pwd.getpwnam(user).pw_gid).gr_name
except KeyError:
log.LOGGER.debug("The PAM user (%s) doesn't exist" % user)
return False

# Check whether the user belongs to the required group
# (primary or supplementary)
if primary_group == group or user in members:
log.LOGGER.debug(
"The PAM user belongs to the required group (%s)" %group)
return True
else:
log.LOGGER.debug(
"The PAM user doesn't belong to the required group (%s)" %group)
return False
13 changes: 13 additions & 0 deletions radicale/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def load():
module = getattr(root_module, auth_type)
# Override auth.is_authenticated
sys.modules[__name__].is_authenticated = module.is_authenticated
# Override auth.is_in_group if available
if hasattr(module, 'is_in_group'):
sys.modules[__name__].is_in_group = module.is_in_group
return module


Expand All @@ -54,3 +57,13 @@ def is_authenticated(user, password):

"""
return True # Default is always True: no authentication


def is_in_group(user, group):
"""Check if the user is in the aforementioned group.

This method is overriden if an auth module providing group support is
loaded.

"""
return False # Default is always False: user in no group
20 changes: 14 additions & 6 deletions radicale/rights/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
import sys
import os.path

from .. import config, log
from .. import config, log, auth

# Manage Python2/3 different modules
if sys.version_info[0] == 2:
from ConfigParser import ConfigParser
from ConfigParser import ConfigParser, NoOptionError
from StringIO import StringIO
else:
from configparser import ConfigParser
from configparser import ConfigParser, NoOptionError
from io import StringIO


Expand Down Expand Up @@ -81,16 +81,24 @@ def _read_from_sections(user, collection_url, permission):
for section in regex.sections():
re_user = regex.get(section, "user")
re_collection = regex.get(section, "collection")
group = []
try:
group = regex.get(section, "group", [])
except NoOptionError:
pass
if group:
group = [ x.strip() for x in group.split(',') ]
log.LOGGER.debug(
"Test if '%s:%s' matches against '%s:%s' from section '%s'" % (
user, collection_url, re_user, re_collection, section))
user_match = re.match(re_user, user)
if user_match:
re_collection = re_collection.format(*user_match.groups())
if re.match(re_collection, collection_url):
log.LOGGER.debug("Section '%s' matches" % section)
if permission in regex.get(section, "permission"):
return True
if any(map(lambda g: auth.is_in_group(user, g), group)):
log.LOGGER.debug("Section '%s' matches" % section)
if permission in regex.get(section, "permission"):
return True
else:
log.LOGGER.debug("Section '%s' does not match" % section)
return False
Expand Down
8 changes: 8 additions & 0 deletions rights
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,11 @@ permission: r
user: .+
collection: ^%(login)s/.*$
permission: w

# Give access to all user in groups admins and wheel to collections starting by
# admins/.
[admins]
user: .+
group: admins, wheel
collection: ^admins/.+$
permission: rw