httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christian Seiler <chris...@gmx.net>
Subject [PATCH] Allow AuthZ providers to supply group data to other modules
Date Fri, 11 Dec 2009 23:03:26 GMT
Hello,

I've attached a patch against a current httpd trunk (r889829) to address
a limitation in the current authorization system. I've been using a
similar patch against Apache 2.2 for quite some time on my own system
and I've finally found the time to port it to the current trunk. I would
thus like to propose the attached patch.

Rationale
======================================================================

I've been using a setup with Apache 2.2 and SVN over WebDAV. The SVN
repository has access restrictions via mod_authz_svn. In the
AuthzSVNAccessFile there is the possibility to restrict access to
different paths based on group membership of users. However, group
membership information also has to be specified in the same file.

In my setup, users are found in a central LDAP directory where also
group information (also used for other purposes) is stored and are
authenticated via mod_authnz_ldap.

My goal is to be able to use the group membership information from the
LDAP directory in connection with the access restrictions of mod_authz_svn.

I'm not the first person to have this request. The first request for
this I found on the SVN mailing list [1]. A year later a patch agains
the SVN authz module was added that directly added native LDAP support
into it [2]. Also, somebody postet a python script that dumps LDAP group
information into the AuthzSVNAccessFile to the SVN mailing list. [3]

Both approaches seem inadequate to me: Native LDAP support in the SVN
module essentially blows up the functionality of mod_authz_svn (what if
somebody wants to have groups in a SQL database? Or a DBM group file?
Or...?) And having an external script update the file periodically is
likely to be error-prone.

My approach is thus to provide a simple mechanism within the Apache API
which allows any authz module to export group information to other
modules. With this mechanism in place, it is possible to change
mod_authz_svn in a way that allows it to use a generic group storage
that it fetches from any used Apache authz module. The change in
mod_authz_svn is of course not the focus of this posting.

[1] http://svn.haxx.se/users/archive-2006-04/0929.shtml
[2] http://svn.haxx.se/dev/archive-2006-07/0107.shtml
[3] http://svn.haxx.se/users/archive-2006-10/0673.shtml

Design
======================================================================

The basic idea behind the design is simple. The struct authz_provider
gains two additional members:

    /* For a given user, return a list of groups the user belongs to. */
    apr_status_t (*get_user_groups)(request_rec *r, const char *user,
                                    apr_table_t **out);
    /* Determine if a user belongs to a specific group. */
    authz_group_status (*user_in_group)(request_rec *r, const char *user,
                                        const char *group);

(Previously, it only contained check_authorization.)

The first function returns a list of all the groups a user belongs to.
The second function determines whether a specific user is member of a
specific group.

NOTE: Both of the new entries of authz_provider MAY BE NULL if a
specific authz_provider does not have anything to do with group support.
For example, the "valid-user" authz_provider provided by mod_authz_user
will have both entries set to NULL. Whereas mod_authz_groupfile will set
both entries for the "group" authz_provider. It is always the
responsibility of the calling module to check whether the authz_provider
actually can provide this information.

Implications for current modules
======================================================================

This design has some implications for existing modules. Especially, the
whole logic of mod_authz_owner and its interactions can be changed:

Current situation (trunk):

 * mod_authz_owner exports a function authz_owner_get_file_group. This
   function is imported by mod_authz_groupfile and mod_authz_dbm.
 * "file-group" is an authz_provider defined in mod_authz_groupfile,
   "dbm-file-group" in mod_authz_dbm. These authz providers use the
   imported function to determine the group of the file that is being
   accessed and then compare it to the group list obtained by the
   groupfile/dbm module itself.

This is of course not optimal since every module that wants to support
checking the owner group of the accessed file against the group list
from the own storage (be it groupfile, DBM, SQL database, LDAP, ...) has
to reimplement part of the mod_authz_owner functionality. If somebody
were to devise a module mod_authz_dirowner which checks it against the
owner of the containing directory, in order for this functionality to be
usable it would have to be added to those modules as well. Incidentally,
since only groupfile/dbm implement the import of mod_authz_owner's
function, SQL & LDAP based groups can currently *not* be checked against
the filesystem group.

New approach (attached patch):

 * Every module that implements a group storage (groupfile, dbm, dbd
   and ldap) implements the user_in_group() function and exports it
   via the authz_provider structure.
 * mod_authz_owner has a new configuration option which tells it which
   other authz_provider it should use: AuthzOwnerGroupProvider.
 * mod_authz_owner now implements file-group (and not groupfile anymore)
   whereas dbm-file-group does not exist any more. [*]

This then clearly separates the modules from each other: groupfile, dbm,
dbd & ldap only provider group storage information whereas
mod_authz_owner is now solely responsible for testing filesystem ownership.

Now even the following makes sense:

AuthzOwnerGroupProvider ldap-group
Require file-group

And without mod_authnz_ldap even knowing about it it is possible to use
a LDAP group storage for checks against the filesystem group of the
accessed resource.

For other internal modules, nothing changes, since the

[*] Of course it would be possible to have some kind of compatibility
scheme with previous configurations. For example, if
AuthzOwnerGroupProvider is not set, it should default to "group"
(authz_provider of mod_authz_groupfile) and mod_authz_owner also exports
"dbm-file-group" which always uses "dbm-group" as a group provider. This
compatibility scheme was not included in the patch but is trivial to
implement.

Notes on the configuration wrt. mod_authz_owner
======================================================================

There are some subtle changes to the configuration for
dbm-file-group/file-group (if one doesn't use the compatibility scheme
as described above).

Example for previous configuration:

AuthGroupFile /.../groups
AuthDBMGroupFile /.../groups.dbm

<RequireAny>
  Require file-group
  Require dbm-file-group
</RequireAny>

Example for current configuration:

AuthGroupFile /.../groups
AuthDBMGroupFile /.../groups.dbm

<AuthzProviderAlias file-group alias-groupfile-file-group>
  AuthzOwnerGroupProvider group
</AuthzProviderAlias>

<AuthzProviderAlias file-group alias-dbm-file-group>
  AuthzOwnerGroupProvider dbm-group
</AuthzProviderAlias>

<RequireAny>
  Require alias-groupfile-file-group
  Require alias-dbm-file-group
</RequireAny>

Open issues
======================================================================

I'm not really sure if it is necessary to have the get_user_groups()
functionality. The main added complexity of the LDAP modules comes from
the fact that the util_ldap module has to be extended by an additional
cache type that stores multi-row-results. Also note that LDAP group
listing does not support subgroups yet, whereas checking membership
does. Also, I haven't found a possible application for this function yet
(not even the original goal of mine, mod_authz_svn, needs it) and so it
may very well be the better choice to remove that and simply stick to
user_in_group() - in which case the patch would get much shorter. In any
case, I've attached a simple demo module mod_grouplist.c that
demonstrates the get groups for user functionality (I've used it to test
the 4 authz modules).

Final remarks
======================================================================

I hope I've shown that the feature I wanted is also very useful for the
current modules as it makes the dependencies with mod_authz_owner much
clearer. I'm sure the patch needs some more polishing but I do hope you
agree that this feature should be added to Apache httpd.

Regards,
Christian

Diffstat for the patch (svn diff -x -p | diffstat):

 include/mod_auth.h                 |   12 +
 include/util_ldap.h                |   29 ++
 modules/aaa/mod_authnz_ldap.c      |  394
+++++++++++++++++++++++++++++++++++--
 modules/aaa/mod_authz_core.c       |    4
 modules/aaa/mod_authz_dbd.c        |   85 +++++++
 modules/aaa/mod_authz_dbm.c        |  118 +++++------
 modules/aaa/mod_authz_groupfile.c  |   99 +++------
 modules/aaa/mod_authz_host.c       |    8
 modules/aaa/mod_authz_owner.c      |   88 ++++++--
 modules/aaa/mod_authz_user.c       |    4
 modules/ldap/util_ldap.c           |  203 +++++++++++++++++++
 modules/ldap/util_ldap_cache.c     |  159 ++++++++++++++
 modules/ldap/util_ldap_cache.h     |   19 +
 modules/ldap/util_ldap_cache_mgr.c |   43 +++-
 14 files changed, 1106 insertions(+), 159 deletions(-)

Mime
View raw message