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 committed Nov 8, 2024
1 parent 8f0b000 commit 95fc762
Showing 1 changed file with 86 additions and 1 deletion.
87 changes: 86 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,87 @@ 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 **p;
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 95fc762

Please sign in to comment.