2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2021-12-05 21:05:27 +05:30
|
|
|
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
|
|
|
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
|
|
|
|
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
|
|
|
* SPDX-FileCopyrightText: 2008 - 2009, Nicolas François
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
2021-12-05 21:05:27 +05:30
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
/* Newer versions of Linux libc already have shadow support. */
|
2007-10-07 17:16:07 +05:30
|
|
|
#if defined(SHADOWGRP) && !defined(HAVE_SHADOWGRP) /*{ */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-11-11 05:16:11 +05:30
|
|
|
#ident "$Id$"
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <stdio.h>
|
Use strlcpy(3) instead of its pattern
- Since strncpy(3) is not designed to write strings, but rather
(null-padded) character sequences (a.k.a. unterminated strings), we
had to manually append a '\0'. strlcpy(3) creates strings, so they
are always terminated. This removes dependencies between lines, and
also removes chances of accidents.
- Repurposing strncpy(3) to create strings requires calculating the
location of the terminating null byte, which involves a '-1'
calculation. This is a source of off-by-one bugs. The new code has
no '-1' calculations, so there's almost-zero chance of these bugs.
- strlcpy(3) doesn't padd with null bytes. Padding is relevant when
writing fixed-width buffers to binary files, when interfacing certain
APIs (I believe utmpx requires null padding at lease in some
systems), or when sending them to other processes or through the
network. This is not the case, so padding is effectively ignored.
- strlcpy(3) requires that the input string is really a string;
otherwise it crashes (SIGSEGV). Let's check if the input strings are
really strings:
- lib/fields.c:
- 'cp' was assigned from 'newft', and 'newft' comes from fgets(3).
- lib/gshadow.c:
- strlen(string) is calculated a few lines above.
- libmisc/console.c:
- 'cons' comes from getdef_str, which is a bit cryptic, but seems
to generate strings, I guess.1
- libmisc/date_to_str.c:
- It receives a string literal. :)
- libmisc/utmp.c:
- 'tname' comes from ttyname(3), which returns a string.
- src/su.c:
- 'tmp_name' has been passed to strcmp(3) a few lines above.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-16 08:43:53 +05:30
|
|
|
#include <string.h>
|
2023-02-05 03:11:18 +05:30
|
|
|
|
|
|
|
#include "alloc.h"
|
2007-10-07 17:14:02 +05:30
|
|
|
#include "prototypes.h"
|
|
|
|
#include "defines.h"
|
2023-02-05 03:11:18 +05:30
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
static /*@null@*/FILE *shadow;
|
|
|
|
static /*@null@*//*@only@*/char **members = NULL;
|
2007-10-07 17:16:07 +05:30
|
|
|
static size_t nmembers = 0;
|
2009-04-23 17:23:55 +05:30
|
|
|
static /*@null@*//*@only@*/char **admins = NULL;
|
2007-10-07 17:16:07 +05:30
|
|
|
static size_t nadmins = 0;
|
|
|
|
static struct sgrp sgroup;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#define FIELDS 4
|
|
|
|
|
|
|
|
#ifdef USE_NIS
|
2008-05-26 14:10:04 +05:30
|
|
|
static bool nis_used;
|
2008-06-14 03:15:47 +05:30
|
|
|
static bool nis_ignore;
|
2007-10-07 17:16:07 +05:30
|
|
|
static enum { native, start, middle, native2 } nis_state;
|
2008-05-26 14:10:04 +05:30
|
|
|
static bool nis_bound;
|
2007-10-07 17:16:07 +05:30
|
|
|
static char *nis_domain;
|
|
|
|
static char *nis_key;
|
|
|
|
static int nis_keylen;
|
|
|
|
static char *nis_val;
|
|
|
|
static int nis_vallen;
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#define IS_NISCHAR(c) ((c)=='+')
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_NIS
|
|
|
|
/*
|
|
|
|
* bind_nis - bind to NIS server
|
|
|
|
*/
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
static int bind_nis (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
if (yp_get_default_domain (&nis_domain))
|
|
|
|
return -1;
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
nis_bound = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
static /*@null@*/char **build_list (char *s, char **list[], size_t * nlist)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:16:07 +05:30
|
|
|
char **ptr = *list;
|
|
|
|
size_t nelem = *nlist, size;
|
|
|
|
|
|
|
|
while (s != NULL && *s != '\0') {
|
|
|
|
size = (nelem + 1) * sizeof (ptr);
|
2023-02-05 03:11:18 +05:30
|
|
|
ptr = REALLOCARRAY (*list, size, char *);
|
2008-07-12 03:53:42 +05:30
|
|
|
if (NULL != ptr) {
|
2008-06-14 03:15:47 +05:30
|
|
|
ptr[nelem] = s;
|
|
|
|
nelem++;
|
2007-10-07 17:16:07 +05:30
|
|
|
*list = ptr;
|
|
|
|
*nlist = nelem;
|
2008-06-14 03:15:47 +05:30
|
|
|
s = strchr (s, ',');
|
|
|
|
if (NULL != s) {
|
|
|
|
*s = '\0';
|
|
|
|
s++;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
size = (nelem + 1) * sizeof (ptr);
|
2023-02-05 03:11:18 +05:30
|
|
|
ptr = REALLOCARRAY (*list, size, char *);
|
2008-06-14 03:15:47 +05:30
|
|
|
if (NULL != ptr) {
|
|
|
|
ptr[nelem] = NULL;
|
2007-10-07 17:16:07 +05:30
|
|
|
*list = ptr;
|
|
|
|
}
|
|
|
|
return ptr;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
void setsgent (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
#ifdef USE_NIS
|
|
|
|
nis_state = native;
|
|
|
|
#endif
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL != shadow) {
|
2007-10-07 17:14:02 +05:30
|
|
|
rewind (shadow);
|
2008-05-26 14:10:04 +05:30
|
|
|
} else {
|
2007-10-07 17:16:07 +05:30
|
|
|
shadow = fopen (SGROUP_FILE, "r");
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
void endsgent (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL != shadow) {
|
2007-10-07 17:14:02 +05:30
|
|
|
(void) fclose (shadow);
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2023-02-01 07:20:14 +05:30
|
|
|
shadow = NULL;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
/*@observer@*//*@null@*/struct sgrp *sgetsgent (const char *string)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2009-06-12 23:20:24 +05:30
|
|
|
static char *sgrbuf = NULL;
|
|
|
|
static size_t sgrbuflen = 0;
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
char *fields[FIELDS];
|
|
|
|
char *cp;
|
|
|
|
int i;
|
2009-06-12 23:20:24 +05:30
|
|
|
size_t len = strlen (string) + 1;
|
|
|
|
|
|
|
|
if (len > sgrbuflen) {
|
2023-02-05 03:11:18 +05:30
|
|
|
char *buf = REALLOCARRAY (sgrbuf, len, char);
|
2009-06-12 23:20:24 +05:30
|
|
|
if (NULL == buf) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
sgrbuf = buf;
|
|
|
|
sgrbuflen = len;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2023-03-11 13:32:45 +05:30
|
|
|
strcpy (sgrbuf, string);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
cp = strrchr (sgrbuf, '\n');
|
|
|
|
if (NULL != cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp = '\0';
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* There should be exactly 4 colon separated fields. Find
|
|
|
|
* all 4 of them and save the starting addresses in fields[].
|
|
|
|
*/
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
for (cp = sgrbuf, i = 0; (i < FIELDS) && (NULL != cp); i++) {
|
2007-10-07 17:14:02 +05:30
|
|
|
fields[i] = cp;
|
2008-05-26 14:10:04 +05:30
|
|
|
cp = strchr (cp, ':');
|
|
|
|
if (NULL != cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp++ = '\0';
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there was an extra field somehow, or perhaps not enough,
|
|
|
|
* the line is invalid.
|
|
|
|
*/
|
|
|
|
|
2009-06-12 23:20:24 +05:30
|
|
|
if ((NULL != cp) || (i != FIELDS)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef USE_NIS
|
2008-05-26 14:10:04 +05:30
|
|
|
if (!IS_NISCHAR (fields[0][0])) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-05-26 14:10:04 +05:30
|
|
|
} else {
|
|
|
|
nis_used = true;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
2009-06-12 23:20:24 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
sgroup.sg_name = fields[0];
|
|
|
|
sgroup.sg_passwd = fields[1];
|
2008-05-26 14:10:04 +05:30
|
|
|
if (0 != nadmins) {
|
2007-10-07 17:16:07 +05:30
|
|
|
nadmins = 0;
|
|
|
|
free (admins);
|
|
|
|
admins = NULL;
|
|
|
|
}
|
2008-05-26 14:10:04 +05:30
|
|
|
if (0 != nmembers) {
|
2007-10-07 17:16:07 +05:30
|
|
|
nmembers = 0;
|
|
|
|
free (members);
|
|
|
|
members = NULL;
|
|
|
|
}
|
2008-01-05 19:26:21 +05:30
|
|
|
sgroup.sg_adm = build_list (fields[2], &admins, &nadmins);
|
|
|
|
sgroup.sg_mem = build_list (fields[3], &members, &nmembers);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
return &sgroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* fgetsgent - convert next line in stream to (struct sgrp)
|
|
|
|
*
|
|
|
|
* fgetsgent() reads the next line from the provided stream and
|
|
|
|
* converts it to a (struct sgrp). NULL is returned on EOF.
|
|
|
|
*/
|
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
/*@observer@*//*@null@*/struct sgrp *fgetsgent (/*@null@*/FILE * fp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2009-06-12 23:20:24 +05:30
|
|
|
static size_t buflen = 0;
|
|
|
|
static char *buf = NULL;
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
char *cp;
|
2009-06-12 23:20:24 +05:30
|
|
|
|
|
|
|
if (0 == buflen) {
|
2023-02-05 03:11:18 +05:30
|
|
|
buf = MALLOCARRAY (BUFSIZ, char);
|
2009-06-12 23:20:24 +05:30
|
|
|
if (NULL == buf) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-11 04:00:03 +05:30
|
|
|
buflen = BUFSIZ;
|
2009-06-12 23:20:24 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL == fp) {
|
2009-06-12 23:20:24 +05:30
|
|
|
return NULL;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#ifdef USE_NIS
|
2023-02-01 18:20:48 +05:30
|
|
|
while (fgetsx (buf, buflen, fp) == buf)
|
2007-10-07 17:14:02 +05:30
|
|
|
#else
|
2023-02-01 18:20:48 +05:30
|
|
|
if (fgetsx (buf, buflen, fp) == buf)
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
|
|
|
{
|
2009-06-12 23:20:24 +05:30
|
|
|
while ( ((cp = strrchr (buf, '\n')) == NULL)
|
|
|
|
&& (feof (fp) == 0)) {
|
|
|
|
size_t len;
|
|
|
|
|
2023-02-05 03:11:18 +05:30
|
|
|
cp = REALLOCARRAY (buf, buflen * 2, char);
|
2009-06-12 23:20:24 +05:30
|
|
|
if (NULL == cp) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
buf = cp;
|
|
|
|
buflen *= 2;
|
|
|
|
|
|
|
|
len = strlen (buf);
|
|
|
|
if (fgetsx (&buf[len],
|
|
|
|
(int) (buflen - len),
|
|
|
|
fp) != &buf[len]) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cp = strrchr (buf, '\n');
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL != cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp = '\0';
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef USE_NIS
|
2008-06-14 03:15:47 +05:30
|
|
|
if (nis_ignore && IS_NISCHAR (buf[0])) {
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
|
|
|
return (sgetsgent (buf));
|
|
|
|
}
|
2009-06-12 23:20:24 +05:30
|
|
|
return NULL;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* getsgent - get a single shadow group entry
|
|
|
|
*/
|
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
/*@observer@*//*@null@*/struct sgrp *getsgent (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
#ifdef USE_NIS
|
2008-06-14 03:15:47 +05:30
|
|
|
bool nis_1_group = false;
|
2007-10-07 17:16:07 +05:30
|
|
|
struct sgrp *val;
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL == shadow) {
|
2007-10-07 17:14:02 +05:30
|
|
|
setsgent ();
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#ifdef USE_NIS
|
2007-10-07 17:16:07 +05:30
|
|
|
again:
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* See if we are reading from the local file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (nis_state == native || nis_state == native2) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the next entry from the shadow group file. Return
|
|
|
|
* NULL right away if there is none.
|
|
|
|
*/
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
val = fgetsgent (shadow);
|
|
|
|
if (NULL == val) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* If this entry began with a NIS escape character, we have
|
|
|
|
* to see if this is just a single group, or if the entire
|
|
|
|
* map is being asked for.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (IS_NISCHAR (val->sg_name[0])) {
|
2008-05-26 14:10:04 +05:30
|
|
|
if ('\0' != val->sg_name[1]) {
|
2008-06-14 03:15:47 +05:30
|
|
|
nis_1_group = true;
|
2008-05-26 14:10:04 +05:30
|
|
|
} else {
|
2007-10-07 17:14:02 +05:30
|
|
|
nis_state = start;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this isn't a NIS group and this isn't an escape to go
|
|
|
|
* use a NIS map, it must be a regular local group.
|
|
|
|
*/
|
|
|
|
|
2008-06-14 03:15:47 +05:30
|
|
|
if (!nis_1_group && (nis_state != start)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return val;
|
2008-06-14 03:15:47 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is an escape to use an NIS map, switch over to
|
|
|
|
* that bunch of code.
|
|
|
|
*/
|
|
|
|
|
2008-06-14 03:15:47 +05:30
|
|
|
if (nis_state == start) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto again;
|
2008-06-14 03:15:47 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* NEEDSWORK. Here we substitute pieces-parts of this entry.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} else {
|
2008-05-26 14:10:04 +05:30
|
|
|
if (!nis_bound) {
|
2007-10-07 17:14:02 +05:30
|
|
|
if (bind_nis ()) {
|
|
|
|
nis_state = native2;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nis_state == start) {
|
|
|
|
if (yp_first (nis_domain, "gshadow.byname", &nis_key,
|
2007-10-07 17:16:07 +05:30
|
|
|
&nis_keylen, &nis_val, &nis_vallen)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nis_state = native2;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
nis_state = middle;
|
|
|
|
} else if (nis_state == middle) {
|
|
|
|
if (yp_next (nis_domain, "gshadow.byname", nis_key,
|
2007-10-07 17:16:07 +05:30
|
|
|
nis_keylen, &nis_key, &nis_keylen,
|
|
|
|
&nis_val, &nis_vallen)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nis_state = native2;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sgetsgent (nis_val);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return (fgetsgent (shadow));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* getsgnam - get a shadow group entry by name
|
|
|
|
*/
|
|
|
|
|
2009-04-23 17:23:55 +05:30
|
|
|
/*@observer@*//*@null@*/struct sgrp *getsgnam (const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:16:07 +05:30
|
|
|
struct sgrp *sgrp;
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef USE_NIS
|
2007-10-07 17:16:07 +05:30
|
|
|
static char save_name[16];
|
|
|
|
int nis_disabled = 0;
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
|
|
|
|
|
|
|
setsgent ();
|
|
|
|
|
|
|
|
#ifdef USE_NIS
|
|
|
|
if (nis_used) {
|
2007-10-07 17:16:07 +05:30
|
|
|
again:
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Search the gshadow.byname map for this group.
|
|
|
|
*/
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
if (!nis_bound) {
|
2007-10-07 17:14:02 +05:30
|
|
|
bind_nis ();
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (nis_bound) {
|
2007-10-07 17:16:07 +05:30
|
|
|
char *cp;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (yp_match (nis_domain, "gshadow.byname", name,
|
2007-10-07 17:16:07 +05:30
|
|
|
strlen (name), &nis_val,
|
|
|
|
&nis_vallen) == 0) {
|
2008-05-26 14:10:04 +05:30
|
|
|
cp = strchr (nis_val, '\n');
|
|
|
|
if (NULL != cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp = '\0';
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
nis_state = middle;
|
2008-05-26 14:10:04 +05:30
|
|
|
sgrp = sgetsgent (nis_val);
|
|
|
|
if (NULL != sgrp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
strcpy (save_name, sgrp->sg_name);
|
|
|
|
nis_key = save_name;
|
|
|
|
nis_keylen = strlen (save_name);
|
|
|
|
}
|
|
|
|
return sgrp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nis_state = native2;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef USE_NIS
|
|
|
|
if (nis_used) {
|
2008-06-14 03:15:47 +05:30
|
|
|
nis_ignore = true;
|
2008-05-26 14:10:04 +05:30
|
|
|
nis_disabled = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
#endif
|
2023-02-01 07:20:14 +05:30
|
|
|
while ((sgrp = getsgent ()) != NULL) {
|
2008-05-26 14:10:04 +05:30
|
|
|
if (strcmp (name, sgrp->sg_name) == 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
#ifdef USE_NIS
|
2008-06-14 03:15:47 +05:30
|
|
|
nis_ignore = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
#endif
|
2008-05-26 14:10:04 +05:30
|
|
|
return sgrp;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* putsgent - output shadow group entry in text form
|
|
|
|
*
|
|
|
|
* putsgent() converts the contents of a (struct sgrp) to text and
|
|
|
|
* writes the result to the given stream. This is the logical
|
|
|
|
* opposite of fgetsgent.
|
|
|
|
*/
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int putsgent (const struct sgrp *sgrp, FILE * fp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
char *buf, *cp;
|
|
|
|
int i;
|
|
|
|
size_t size;
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
if ((NULL == fp) || (NULL == sgrp)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/* calculate the required buffer size */
|
2007-10-07 17:16:07 +05:30
|
|
|
size = strlen (sgrp->sg_name) + strlen (sgrp->sg_passwd) + 10;
|
2008-05-26 14:10:04 +05:30
|
|
|
for (i = 0; (NULL != sgrp->sg_adm) && (NULL != sgrp->sg_adm[i]); i++) {
|
2007-10-07 17:16:07 +05:30
|
|
|
size += strlen (sgrp->sg_adm[i]) + 1;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
|
|
|
for (i = 0; (NULL != sgrp->sg_mem) && (NULL != sgrp->sg_mem[i]); i++) {
|
2007-10-07 17:16:07 +05:30
|
|
|
size += strlen (sgrp->sg_mem[i]) + 1;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2023-02-05 03:11:18 +05:30
|
|
|
buf = MALLOCARRAY (size, char);
|
2008-05-26 14:10:04 +05:30
|
|
|
if (NULL == buf) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
cp = buf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the group name and passwd.
|
|
|
|
*/
|
|
|
|
|
|
|
|
strcpy (cp, sgrp->sg_name);
|
|
|
|
cp += strlen (cp);
|
|
|
|
*cp++ = ':';
|
|
|
|
|
|
|
|
strcpy (cp, sgrp->sg_passwd);
|
|
|
|
cp += strlen (cp);
|
|
|
|
*cp++ = ':';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the administrators, separating each from the other
|
|
|
|
* with a ",".
|
|
|
|
*/
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
for (i = 0; NULL != sgrp->sg_adm[i]; i++) {
|
|
|
|
if (i > 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp++ = ',';
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
strcpy (cp, sgrp->sg_adm[i]);
|
|
|
|
cp += strlen (cp);
|
|
|
|
}
|
2009-04-23 17:23:55 +05:30
|
|
|
*cp = ':';
|
|
|
|
cp++;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Now do likewise with the group members.
|
|
|
|
*/
|
|
|
|
|
2008-05-26 14:10:04 +05:30
|
|
|
for (i = 0; NULL != sgrp->sg_mem[i]; i++) {
|
|
|
|
if (i > 0) {
|
2008-06-14 03:15:47 +05:30
|
|
|
*cp = ',';
|
|
|
|
cp++;
|
2008-05-26 14:10:04 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
strcpy (cp, sgrp->sg_mem[i]);
|
|
|
|
cp += strlen (cp);
|
|
|
|
}
|
2008-06-14 03:15:47 +05:30
|
|
|
*cp = '\n';
|
|
|
|
cp++;
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Output using the function which understands the line
|
|
|
|
* continuation conventions.
|
|
|
|
*/
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
if (fputsx (buf, fp) == EOF) {
|
|
|
|
free (buf);
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
free (buf);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
2022-12-21 23:32:25 +05:30
|
|
|
extern int ISO_C_forbids_an_empty_translation_unit;
|
2007-10-07 17:16:07 +05:30
|
|
|
#endif /*} SHADOWGRP */
|