Skip to content
Draft
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
2 changes: 2 additions & 0 deletions src/config/SSSDConfig/sssdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ def __init__(self):
'ldap_group_nesting_level': _('Maximum nesting level SSSD will follow'),
'ldap_group_search_filter': _('Filter for group lookups'),
'ldap_group_search_scope': _('Scope of group lookups'),
'ldap_group_absent_gid_local': _('Use gid from /etc/group if group has no LDAP gid attribute'),
'ldap_group_negative_gid_local': _('Use gid from /etc/group if LDAP gid is negative'),

'ldap_netgroup_search_base': _('Base DN for netgroup lookups'),
'ldap_netgroup_object_class': _('Objectclass for netgroups'),
Expand Down
2 changes: 2 additions & 0 deletions src/config/cfg_rules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -635,12 +635,14 @@ option = ldap_enumeration_refresh_timeout
option = ldap_enumeration_refresh_offset
option = ldap_enumeration_search_timeout
option = ldap_force_upper_case_realm
option = ldap_group_absent_gid_local
option = ldap_group_entry_usn
option = ldap_group_external_member
option = ldap_group_gid_number
option = ldap_group_member
option = ldap_group_modify_timestamp
option = ldap_group_name
option = ldap_group_negative_gid_local
option = ldap_group_nesting_level
option = ldap_group_object_class
option = ldap_group_objectsid
Expand Down
50 changes: 50 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,56 @@
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_group_negative_gid_local</term>
<listitem>
<para>
Enables merging LDAP groups with negative gid values
with local groups of the same name, picking up the
local gid. This is intended for assigning system
groups to users, e.g. the audio or bluetooth groups.
Any negative value is accepted in order to allow
the LDAP server to enforce uniqueness constraints on
gids for other groups. This option is preferable
over the one below (gid attribute entirely absent)
since it has a lower risk of unintended side effects.
</para>
<para>
Note this specifically checks local groups in
/etc/group; other sources of group IDs are not
considered. It must be combined with
"files [SUCCESS=merge] sss" in /etc/nssswitch.conf.
</para>
<para>
Default: False
</para>
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_group_absent_gid_local</term>
<listitem>
<para>
Enables merging LDAP groups without gid attribute
with local groups of the same name, picking up the
local gid. This is intended for assigning system
groups to users, e.g. the audio or bluetooth groups.
Note that this may result in mapping some LDAP groups
that were not intended as POSIX groups, if they have
the same name.
</para>
<para>
Note this specifically checks local groups in
/etc/group; other sources of group IDs are not
considered. It must be combined with
"files [SUCCESS=merge] sss" in /etc/nssswitch.conf.
</para>
<para>
Default: False
</para>
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_sasl_mech (string)</term>
<listitem>
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/ldap_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct dp_option default_basic_opts[] = {
{ "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
{ "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_group_absent_gid_local", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "ldap_group_negative_gid_local", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "ldap_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_service_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/sdap.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ enum sdap_basic_opt {
SDAP_GROUP_SEARCH_BASE,
SDAP_GROUP_SEARCH_SCOPE,
SDAP_GROUP_SEARCH_FILTER,
SDAP_GROUP_ABSENT_GID_LOCAL,
SDAP_GROUP_NEGATIVE_GID_LOCAL,
SDAP_HOST_SEARCH_BASE,
SDAP_SERVICE_SEARCH_BASE,
SDAP_SUDO_SEARCH_BASE,
Expand Down
85 changes: 85 additions & 0 deletions src/providers/ldap/sdap_async_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ static int sdap_save_group(TALLOC_CTX *memctx,
group_name, dom->name);
ret = EINVAL;
goto done;
} else {
DEBUG(SSSDBG_TRACE_FUNC,
"gid provided for [%s] in domain [%s] is %d.\n",
group_name, dom->name, (int)gid);
}
}
}
Expand Down Expand Up @@ -1893,6 +1897,84 @@ static void sdap_search_group_copy_batch(struct sdap_get_groups_state *state,
struct sysdb_attrs **groups,
size_t count);

static void sdap_group_apply_remap(struct sysdb_attrs *attrs,
struct sdap_options *opts) {
int ret;
const char *group_name = NULL;
int32_t gid = -1;
char buf[2048];
char *grname, *p;
struct group gbuf, *gr;

ret = sysdb_attrs_get_string(
attrs, opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &group_name);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "GID remap: group has no group name?\n");
return;
}

ret = sysdb_attrs_get_int32_t(
attrs, opts->group_map[SDAP_AT_GROUP_GID].sys_name, &gid);
switch (ret) {
case EOK:
if (gid >= 0)
return;
if (!dp_opt_get_bool(opts->basic, SDAP_GROUP_NEGATIVE_GID_LOCAL))
return;
break;

case ENOENT:
if (!dp_opt_get_bool(opts->basic, SDAP_GROUP_ABSENT_GID_LOCAL))
return;
break;

default:
return;
}

DEBUG(SSSDBG_TRACE_FUNC, "GID remap: checking group %s\n", group_name);

FILE *etc_group = fopen("/etc/group", "r");
Copy link
Member

@alexey-tikhonov alexey-tikhonov Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely not a way to go.

There is sss_load_nss_symbols() helper in 'util/nss_dl_load.c' that can load 'libnss_files.so.2' to query local files.
But this would leave an open question about nss-altfiles, for example.

JFTR: I don't propose you to put more work into this atm. SSSD had "files provider" in the past (now removed), and idea of going back to messing with local NSS objects isn't too appealing...

if (!etc_group) {
DEBUG(SSSDBG_CRIT_FAILURE, "failed to open /etc/group: %s\n",
strerror(errno));
return;
}

grname = strdup(group_name);
p = strchr(grname, '@');
if (p)
*p = '\0';

while (!fgetgrent_r(etc_group, &gbuf, buf, sizeof(buf), &gr)) {
if (strcmp(gr->gr_name, grname))
continue;

ret = sysdb_attrs_replace_name(
attrs, opts->group_map[SDAP_AT_GROUP_GID].sys_name, "origGid");
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "failed to rename gid attribute on %s\n",
group_name);
break;
}

ret = sysdb_attrs_add_uint32(
attrs, opts->group_map[SDAP_AT_GROUP_GID].sys_name, gr->gr_gid);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "failed to add remapped gid attribute on %s\n",
group_name);
break;
}

DEBUG(SSSDBG_TRACE_FUNC, "GID remap: group %s mapped to local gid %d\n",
group_name, (int)gr->gr_gid);
break;
}

free(grname);
fclose(etc_group);
}

static void sdap_get_groups_process(struct tevent_req *subreq)
{
struct tevent_req *req =
Expand Down Expand Up @@ -1936,6 +2018,9 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
return;
}

for (i = 0; i < count; i++)
sdap_group_apply_remap(groups[i], state->opts);

sdap_search_group_copy_batch(state, groups, count);
}

Expand Down