/* Copyright (C) 1996-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <nss.h>
#include <nsswitch.h>
#include <stdio_ext.h>
#include <string.h>
#include <libc-lock.h>
#include <kernel-features.h>
#include <nss_files.h>
NSS_DECLARE_MODULE_FUNCTIONS (compat)
static nss_action_list ni;
static enum nss_status (*setgrent_impl) (int stayopen);
static enum nss_status (*getgrnam_r_impl) (const char *name,
struct group * grp, char *buffer,
size_t buflen, int *errnop);
static enum nss_status (*getgrgid_r_impl) (gid_t gid, struct group * grp,
char *buffer, size_t buflen,
int *errnop);
static enum nss_status (*getgrent_r_impl) (struct group * grp, char *buffer,
size_t buflen, int *errnop);
static enum nss_status (*endgrent_impl) (void);
/* Get the declaration of the parser function. */
#define ENTNAME grent
#define STRUCTURE group
#define EXTERN_PARSER
#include <nss/nss_files/files-parse.c>
/* Structure for remembering -group members ... */
#define BLACKLIST_INITIAL_SIZE 512
#define BLACKLIST_INCREMENT 256
struct blacklist_t
{
char *data;
int current;
int size;
};
struct ent_t
{
bool files;
enum nss_status setent_status;
FILE *stream;
struct blacklist_t blacklist;
};
typedef struct ent_t ent_t;
static ent_t ext_ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
/* Protect global state against multiple changers. */
__libc_lock_define_initialized (static, lock)
/* Prototypes for local functions. */
static void blacklist_store_name (const char *, ent_t *);
static bool in_blacklist (const char *, int, ent_t *);
/* Initialize the NSS interface/functions. The calling function must
hold the lock. */
static void
init_nss_interface (void)
{
if (__nss_database_get (nss_database_group_compat, &ni))
{
setgrent_impl = __nss_lookup_function (ni, "setgrent");
getgrnam_r_impl = __nss_lookup_function (ni, "getgrnam_r");
getgrgid_r_impl = __nss_lookup_function (ni, "getgrgid_r");
getgrent_r_impl = __nss_lookup_function (ni, "getgrent_r");
endgrent_impl = __nss_lookup_function (ni, "endgrent");
}
}
static enum nss_status
internal_setgrent (ent_t *ent, int stayopen, int needent)
{
enum nss_status