Skip to content

Commit

Permalink
mod_authz_unixgroup: Use getgrouplist
Browse files Browse the repository at this point in the history
Some services, like sssd, can optimize away grp->gr_mem which makes this
module fail group lookup.

Use getgrouplist(3) instead and gid_from_group(3bsd) which uses libbsd,
link with -lbsd.
This avoids the problematic getgrgid()/getgrnam() functions.
  • Loading branch information
joakim-tjernlund authored and bimimicah committed Nov 22, 2024
1 parent 4c97c04 commit 904d513
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 8 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: install apache (ubuntu)
- name: install apache and libbsd (ubuntu)
if: runner.os == 'Linux'
run: sudo apt-get install apache2 apache2-dev
run: sudo apt-get install apache2 apache2-dev libbsd-dev

- name: install apache (macos)
- name: install apache and libbsd (macos)
if: runner.os == 'macOS'
run: brew install httpd
run: brew install httpd libbsd

- name: make mod_authnz_external (POSIX-GCC)
if: runner.os != 'Windows'
Expand Down
6 changes: 5 additions & 1 deletion mod_authz_unixgroup/INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ Step 2:
Compile the module using the following command in the
mod_authz_unixgroup distribution directory:

apxs -c mod_authz_unixgroup.c
apxs -c mod_authz_unixgroup.c -lbsd
Build using just POSIX group interfaces
apxs -c mod_authz_unixgroup.c -DUSE_POSIX_GRP
Note that some group providers(e.g sssd) can optionally omit gr_mem
in struct grp which will make POSIX fail(in addition to beeing slower)

'Apxs' is the Apache extension tool. It is part of the standard
Apache installation. If you don't have it, then your Apache server
Expand Down
4 changes: 2 additions & 2 deletions mod_authz_unixgroup/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ install: mod_authz_unixgroup.la
build: mod_authz_unixgroup.la

mod_authz_unixgroup.la: mod_authz_unixgroup.c
$(APXS) -c mod_authz_unixgroup.c
$(info REMINDER: This project requires libbsd and associated headers to compile and run. Please install any necessary development packages for your platform if you have not already.)
$(APXS) -c mod_authz_unixgroup.c -lbsd

clean:
rm -rf mod_authz_unixgroup.so mod_authz_unixgroup.o \
mod_authz_unixgroup.la mod_authz_unixgroup.slo \
mod_authz_unixgroup.lo .libs
-ls -a .*.swp

tar: mod_authz_unixgroup.tar

Expand Down
86 changes: 85 additions & 1 deletion mod_authz_unixgroup/mod_authz_unixgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
#include <pwd.h>
#endif
#if HAVE_GRP_H
#ifdef USE_POSIX_GRP
#include <grp.h>
#else
#include <bsd/grp.h>
#endif
#endif
#if APR_HAVE_UNISTD_H
#include <unistd.h>
Expand All @@ -41,7 +45,7 @@ APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
* can either be unix group names or numeric group id numbers. There must
* be a unix login corresponding to the named user.
*/

#ifdef USE_POSIX_GRP
static int check_unix_group(request_rec *r, const char *grouplist)
{
char **p;
Expand Down Expand Up @@ -112,6 +116,86 @@ static int check_unix_group(request_rec *r, const char *grouplist)
if (at != NULL) *at= '@';
return 0;
}
#else
#define MAX_USER_GRPS (4*1024)
static int check_unix_group(request_rec *r, const char *grouplist)
{
char *user= r->user;
char *w, *at;
static gid_t groups[MAX_USER_GRPS], gid;
int ngroups = MAX_USER_GRPS, i;

/* Strip @ sign and anything following it from the username. Some
* authentication modules, like mod_auth_kerb like appending such
* stuff to user names, but an @ sign is never legal in a unix login
* name, so it should be safe to always discard such stuff.
*/
if ((at= strchr(user, '@')) != NULL) *at= '\0';

/* Get info about login */
struct passwd *pwd= getpwnam(user);
if (pwd == NULL)
{
/* No such user - forget it */
if (at != NULL) *at= '@';
return 0;
}

if (getgrouplist(user, pwd->pw_gid, groups, &ngroups) < 0)
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Authorization of user %s to access %s failed. "
" getgrouplist(errno:%s).",
r->user, r->uri, strerror(errno));
if (at != NULL) *at= '@';
return 0;
}
/* Loop through list of groups passed in */
while (*grouplist != '\0')
{
w= ap_getword_conf(r->pool, &grouplist);
if (apr_isdigit(w[0]))
{
/* Numeric group id */
gid = atoi(w);
}
else
{
/* Get gid and list of group members for group name */
/* from libbsd */
if (gid_from_group(w, &gid) < 0)
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Authorization of user %s to access %s failed. "
" gid_from_group(errno:%s).",
r->user, r->uri, strerror(errno));
if (at != NULL) *at= '@';
return 0;
}
}
/* Check if it matches the user's primary group */
if (gid == pwd->pw_gid)
{
if (at != NULL) *at= '@';
return 1;
}

/* Walk through list of members, seeing if any match user login */
for(i = 0; i < ngroups; i++)
{
if (gid == groups[i])
{
if (at != NULL) *at= '@';
return 1;
}
}
}

/* Didn't find any matches, flunk him */
if (at != NULL) *at= '@';
return 0;
}
#endif

static authz_status unixgroup_check_authorization(request_rec *r,
const char *require_args, const void *parsed_require_args)
Expand Down

0 comments on commit 904d513

Please sign in to comment.