Skip to content

Commit

Permalink
mod_authz_unixgroup: Use getgrouplist() instead of gr_mem for sssd co…
Browse files Browse the repository at this point in the history
…mpatibility

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 23, 2024
1 parent 4c97c04 commit a59981c
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 94 deletions.
203 changes: 117 additions & 86 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,86 +1,117 @@
name: Build Status

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
name: ${{ matrix.os }} build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
- uses: actions/checkout@v2

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

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

- name: make mod_authnz_external (POSIX-GCC)
if: runner.os != 'Windows'
run: make
working-directory: ./mod_authnz_external

- name: make mod_authz_unixgroup (POSIX-GCC)
if: runner.os != 'Windows'
run: make
working-directory: ./mod_authz_unixgroup

- name: nmake (MSVC)
if: runner.os == 'Windows'
run: |
# find and set APACHEPATH environment variable
$env:APACHEPATH = Join-Path "C:\tools\" (Get-Item C:\tools\apache*).Name
# set it for real, GH Actions uses a new Powershell for each step
[System.Environment]::SetEnvironmentVariable('APACHEPATH',$env:APACHEPATH,'Machine')
# this 'apr_perms_set.h' header is missing from Chocolatey's Apache install
Invoke-WebRequest https://raw.githubusercontent.com/traviscross/apr/master/include/apr_perms_set.h -OutFile (Join-Path ($env:APACHEPATH) "include\apr_perms_set.h")
# call vcvars.bat to setup the environment, then call nmake to build the module
echo "call ""$((Get-VisualStudioInstance).InstallationPath)\VC\Auxiliary\Build\vcvars64.bat""" > winbuild.bat
echo "nmake -f ""$(pwd)\Makefile.win""" >> winbuild.bat
.\winbuild.bat
working-directory: ./mod_authnz_external

- name: make install mod_authnz_external (POSIX-GCC)
if: runner.os != 'Windows'
run: sudo make install
working-directory: ./mod_authnz_external

- name: make install mod_authz_unixgroup (POSIX-GCC)
if: runner.os != 'Windows'
run: sudo make install
working-directory: ./mod_authz_unixgroup

- name: install to apache (windows)
if: runner.os == 'Windows'
run: |
# get APACHEPATH
$env:APACHEPATH = [System.Environment]::GetEnvironmentVariable('APACHEPATH','Machine')
# manually install the compiled module in Apache
cp mod_authnz_external.so (Join-Path ($env:APACHEPATH) "modules\mod_authnz_external.so")
echo "LoadModule authnz_external_module modules/mod_authnz_external.so" >> (Join-Path ($env:APACHEPATH) "conf\httpd.conf")
working-directory: ./mod_authnz_external

- name: restart apache (ubuntu)
if: runner.os == 'Linux'
run: sudo service apache2 restart

- name: restart apache (macos)
if: runner.os == 'macOS'
run: brew services restart httpd

- name: restart apache (windows)
if: runner.os == 'Windows'
run: |
Stop-Service -Name w3svc
Set-Service Apache -StartupType Manual
Start-Service -Name Apache
name: Build Status

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
name: ${{ matrix.os }} build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
- uses: actions/checkout@v2

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

- name: install apache and libbsd (macos)
if: runner.os == 'macOS'
run: |
# use latest master, not stable (until libbsd mac version is in stable)
brew developer on
# grab master version of libbsd with mac support
brew update
brew install httpd libbsd
brew link libbsd
cd /opt/homebrew/opt
ls
cd libbsd
ls
cd include
ls
cd bsd ls
cd /opt/homebrew/Cellar
ls
cd libbsd
ls
cd 0.12.2
ls
cd include
ls
cd bsd
ls
- name: make mod_authnz_external (POSIX-GCC)
if: runner.os != 'Windows'
run: make
working-directory: ./mod_authnz_external

- name: make mod_authz_unixgroup (ubuntu)
if: runner.os == 'Linux'
run: make
working-directory: ./mod_authz_unixgroup

- name: make mod_authz_unixgroup (macos)
if: runner.os == 'macOS'
run: |
#export LDFLAGS="-L/opt/homebrew/lib"
#export CFLAGS="-I/opt/homebrew/opt/libbsd/include"
CFLAGS+=" -I/opt/homebrew/opt/libbsd/include" make
working-directory: ./mod_authz_unixgroup

- name: nmake (MSVC)
if: runner.os == 'Windows'
run: |
# find and set APACHEPATH environment variable
$env:APACHEPATH = Join-Path "C:\tools\" (Get-Item C:\tools\apache*).Name
# set it for real, GH Actions uses a new Powershell for each step
[System.Environment]::SetEnvironmentVariable('APACHEPATH',$env:APACHEPATH,'Machine')
# this 'apr_perms_set.h' header is missing from Chocolatey's Apache install
Invoke-WebRequest https://raw.githubusercontent.com/traviscross/apr/master/include/apr_perms_set.h -OutFile (Join-Path ($env:APACHEPATH) "include\apr_perms_set.h")
# call vcvars.bat to setup the environment, then call nmake to build the module
echo "call ""$((Get-VisualStudioInstance).InstallationPath)\VC\Auxiliary\Build\vcvars64.bat""" > winbuild.bat
echo "nmake -f ""$(pwd)\Makefile.win""" >> winbuild.bat
.\winbuild.bat
working-directory: ./mod_authnz_external

- name: make install mod_authnz_external (POSIX-GCC)
if: runner.os != 'Windows'
run: sudo make install
working-directory: ./mod_authnz_external

- name: make install mod_authz_unixgroup (POSIX-GCC)
if: runner.os != 'Windows'
run: sudo make install
working-directory: ./mod_authz_unixgroup

- name: install to apache (windows)
if: runner.os == 'Windows'
run: |
# get APACHEPATH
$env:APACHEPATH = [System.Environment]::GetEnvironmentVariable('APACHEPATH','Machine')
# manually install the compiled module in Apache
cp mod_authnz_external.so (Join-Path ($env:APACHEPATH) "modules\mod_authnz_external.so")
echo "LoadModule authnz_external_module modules/mod_authnz_external.so" >> (Join-Path ($env:APACHEPATH) "conf\httpd.conf")
working-directory: ./mod_authnz_external

- name: restart apache (ubuntu)
if: runner.os == 'Linux'
run: sudo service apache2 restart

- name: restart apache (macos)
if: runner.os == 'macOS'
run: brew services restart httpd

- name: restart apache (windows)
if: runner.os == 'Windows'
run: |
Stop-Service -Name w3svc
Set-Service Apache -StartupType Manual
Start-Service -Name Apache
Expand Down
1 change: 1 addition & 0 deletions mod_authz_unixgroup/CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ mod_authz_unixgroup is based on code from the following sources:
David Homborg
klemens/ka7
Micah Andersen/Baptist International Missions, Inc. ([email protected])
Joakim Tjernlund/joakim-tjernlund
15 changes: 10 additions & 5 deletions mod_authz_unixgroup/INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ 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

'Apxs' is the Apache extension tool. It is part of the standard
Apache installation. If you don't have it, then your Apache server
is probably not set up for handling dynamically loaded modules.
This should create a file named 'mod_authz_unixgroup.so'.
* 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 break POSIX API (in addition to being 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
is probably not set up for handling dynamically loaded modules.
This should create a file named 'mod_authz_unixgroup.so'.

Step 3:
Install the module. Apxs can do this for you too. Do the following
Expand Down
13 changes: 11 additions & 2 deletions mod_authz_unixgroup/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#APXS=apxs2
APXS=apxs

ifneq (($OS),Windows_NT)
OS := $(shell uname -s)
endif

TAR= README INSTALL NOTICE CHANGES CONTRIBUTORS LICENSE \
mod_authz_unixgroup.c Makefile Makefile.win

Expand All @@ -14,13 +18,18 @@ 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.)
ifeq (($OS),Darwin)
ls
$(APXS) -c mod_authz_unixgroup.c -lbsd -I/opt/homebrew/opt/libbsd/include
else
$(APXS) -c mod_authz_unixgroup.c -lbsd
endif

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 allowed 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 the user's primary group matches allowed group(s) */
if (gid == pwd->pw_gid)
{
if (at != NULL) *at = '@';
return 1;
}

/* Walk through list of user's group(s), seeing if any match allowed group(s) */
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 a59981c

Please sign in to comment.