From 98b107e30848198e7128f80b38b406585f0317d6 Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Mon, 2 Oct 2023 14:55:16 +0200 Subject: Remove 'gshadow' and merge into 'nss' The majority of gshadow routines are entry points for nss functionality. This commit removes the 'gshadow' subdirectory and moves all functionality and tests to 'nss'. References to gshadow/ are accordingly changed. Reviewed-by: Adhemerval Zanella --- Makeconfig | 2 +- gshadow/Makefile | 39 ---------- gshadow/Versions | 21 ----- gshadow/fgetsgent.c | 90 ---------------------- gshadow/fgetsgent_r.c | 46 ----------- gshadow/getsgent.c | 31 -------- gshadow/getsgent_r.c | 32 -------- gshadow/getsgnam.c | 31 -------- gshadow/getsgnam_r.c | 32 -------- gshadow/gshadow.h | 132 ------------------------------- gshadow/putsgent.c | 81 ------------------- gshadow/sgetsgent.c | 77 ------------------- gshadow/sgetsgent_r.c | 77 ------------------- gshadow/tst-fgetsgent_r.c | 192 ---------------------------------------------- gshadow/tst-gshadow.c | 141 ---------------------------------- gshadow/tst-putsgent.c | 168 ---------------------------------------- gshadow/tst-sgetsgent.c | 69 ----------------- include/gshadow.h | 2 +- nss/Makefile | 28 +++++++ nss/Versions | 19 +++++ nss/fgetsgent.c | 90 ++++++++++++++++++++++ nss/fgetsgent_r.c | 46 +++++++++++ nss/getsgent.c | 31 ++++++++ nss/getsgent_r.c | 32 ++++++++ nss/getsgnam.c | 31 ++++++++ nss/getsgnam_r.c | 32 ++++++++ nss/gshadow.h | 132 +++++++++++++++++++++++++++++++ nss/putsgent.c | 81 +++++++++++++++++++ nss/sgetsgent.c | 77 +++++++++++++++++++ nss/sgetsgent_r.c | 77 +++++++++++++++++++ nss/tst-fgetsgent_r.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++ nss/tst-gshadow.c | 141 ++++++++++++++++++++++++++++++++++ nss/tst-putsgent.c | 168 ++++++++++++++++++++++++++++++++++++++++ nss/tst-sgetsgent.c | 69 +++++++++++++++++ 34 files changed, 1248 insertions(+), 1261 deletions(-) delete mode 100644 gshadow/Makefile delete mode 100644 gshadow/Versions delete mode 100644 gshadow/fgetsgent.c delete mode 100644 gshadow/fgetsgent_r.c delete mode 100644 gshadow/getsgent.c delete mode 100644 gshadow/getsgent_r.c delete mode 100644 gshadow/getsgnam.c delete mode 100644 gshadow/getsgnam_r.c delete mode 100644 gshadow/gshadow.h delete mode 100644 gshadow/putsgent.c delete mode 100644 gshadow/sgetsgent.c delete mode 100644 gshadow/sgetsgent_r.c delete mode 100644 gshadow/tst-fgetsgent_r.c delete mode 100644 gshadow/tst-gshadow.c delete mode 100644 gshadow/tst-putsgent.c delete mode 100644 gshadow/tst-sgetsgent.c create mode 100644 nss/fgetsgent.c create mode 100644 nss/fgetsgent_r.c create mode 100644 nss/getsgent.c create mode 100644 nss/getsgent_r.c create mode 100644 nss/getsgnam.c create mode 100644 nss/getsgnam_r.c create mode 100644 nss/gshadow.h create mode 100644 nss/putsgent.c create mode 100644 nss/sgetsgent.c create mode 100644 nss/sgetsgent_r.c create mode 100644 nss/tst-fgetsgent_r.c create mode 100644 nss/tst-gshadow.c create mode 100644 nss/tst-putsgent.c create mode 100644 nss/tst-sgetsgent.c diff --git a/Makeconfig b/Makeconfig index 9ff6a90..ac7fa3d 100644 --- a/Makeconfig +++ b/Makeconfig @@ -1353,7 +1353,7 @@ endif all-subdirs = csu assert ctype locale intl catgets math setjmp signal \ stdlib stdio-common libio malloc string wcsmbs time dirent \ pwd posix io termios resource misc socket sysvipc gmon \ - gnulib iconv iconvdata wctype manual shadow gshadow po argp \ + gnulib iconv iconvdata wctype manual shadow po argp \ localedata timezone rt conform debug mathvec support \ dlfcn elf diff --git a/gshadow/Makefile b/gshadow/Makefile deleted file mode 100644 index a955245..0000000 --- a/gshadow/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2009-2023 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 -# . - -# -# Makefile for gshadow. -# -subdir := gshadow - -include ../Makeconfig - -headers = gshadow.h -routines = getsgent getsgnam sgetsgent fgetsgent putsgent \ - getsgent_r getsgnam_r sgetsgent_r fgetsgent_r - -tests = tst-gshadow tst-putsgent tst-fgetsgent_r tst-sgetsgent - -CFLAGS-getsgent_r.c += -fexceptions -CFLAGS-getsgent.c += -fexceptions -CFLAGS-fgetsgent.c += -fexceptions -CFLAGS-fgetsgent_r.c += -fexceptions $(libio-mtsafe) -CFLAGS-putsgent.c += -fexceptions $(libio-mtsafe) -CFLAGS-getsgnam.c += -fexceptions -CFLAGS-getsgnam_r.c += -fexceptions - -include ../Rules diff --git a/gshadow/Versions b/gshadow/Versions deleted file mode 100644 index 1dba0c5..0000000 --- a/gshadow/Versions +++ /dev/null @@ -1,21 +0,0 @@ -libc { - GLIBC_2.10 { - # e* - endsgent; - - # f* - fgetsgent; fgetsgent_r; - - # g* - getsgent; getsgent_r; getsgnam; getsgnam_r; - - # p* - putsgent; - - # s* - setsgent; - - # s* - sgetsgent; sgetsgent_r; - } -} diff --git a/gshadow/fgetsgent.c b/gshadow/fgetsgent.c deleted file mode 100644 index dc26b24..0000000 --- a/gshadow/fgetsgent.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include -#include -#include -#include -#include -#include - - -/* A reasonable size for a buffer to start with. */ -#define BUFLEN_SPWD 1024 - -/* We need to protect the dynamic buffer handling. */ -__libc_lock_define_initialized (static, lock); - -static char *buffer; - -/* Read one shadow entry from the given stream. */ -struct sgrp * -fgetsgent (FILE *stream) -{ - static size_t buffer_size; - static struct sgrp resbuf; - fpos_t pos; - struct sgrp *result; - int save; - - if (fgetpos (stream, &pos) != 0) - return NULL; - - /* Get lock. */ - __libc_lock_lock (lock); - - /* Allocate buffer if not yet available. */ - if (buffer == NULL) - { - buffer_size = BUFLEN_SPWD; - buffer = malloc (buffer_size); - } - - while (buffer != NULL - && (__fgetsgent_r (stream, &resbuf, buffer, buffer_size, &result) - == ERANGE)) - { - char *new_buf; - buffer_size += BUFLEN_SPWD; - new_buf = realloc (buffer, buffer_size); - if (new_buf == NULL) - { - /* We are out of memory. Free the current buffer so that the - process gets a chance for a normal termination. */ - save = errno; - free (buffer); - __set_errno (save); - } - buffer = new_buf; - - /* Reset the stream. */ - if (fsetpos (stream, &pos) != 0) - buffer = NULL; - } - - if (buffer == NULL) - result = NULL; - - /* Release lock. Preserve error value. */ - save = errno; - __libc_lock_unlock (lock); - __set_errno (save); - - return result; -} - -weak_alias (buffer, __libc_fgetsgent_freeres_ptr); diff --git a/gshadow/fgetsgent_r.c b/gshadow/fgetsgent_r.c deleted file mode 100644 index 54616b9..0000000 --- a/gshadow/fgetsgent_r.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include -#include -#include -#include - -/* Define a line parsing function using the common code - used in the nss_files module. */ - -#define STRUCTURE sgrp -#define ENTNAME sgent -#define EXTERN_PARSER 1 -struct sgent_data {}; - -#include - - -/* Read one shadow entry from the given stream. */ -int -__fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, - struct sgrp **result) -{ - int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); - if (ret == 0) - *result = resbuf; - else - *result = NULL; - return ret; -} -weak_alias (__fgetsgent_r, fgetsgent_r) diff --git a/gshadow/getsgent.c b/gshadow/getsgent.c deleted file mode 100644 index 68f67c0..0000000 --- a/gshadow/getsgent.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include - - -#define LOOKUP_TYPE struct sgrp -#define SETFUNC_NAME setsgent -#define GETFUNC_NAME getsgent -#define ENDFUNC_NAME endsgent -#define DATABASE_NAME gshadow -#define BUFLEN 1024 - -/* There is no nscd support for the shadow file. */ -#undef USE_NSCD - -#include "../nss/getXXent.c" diff --git a/gshadow/getsgent_r.c b/gshadow/getsgent_r.c deleted file mode 100644 index b24ebe1..0000000 --- a/gshadow/getsgent_r.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include - - -#define LOOKUP_TYPE struct sgrp -#define SETFUNC_NAME setsgent -#define GETFUNC_NAME getsgent -#define ENDFUNC_NAME endsgent -#define DATABASE_NAME gshadow -#define BUFLEN 1024 -#define NO_COMPAT_NEEDED 1 - -/* There is no nscd support for the shadow file. */ -#undef USE_NSCD - -#include "../nss/getXXent_r.c" diff --git a/gshadow/getsgnam.c b/gshadow/getsgnam.c deleted file mode 100644 index 3177c86..0000000 --- a/gshadow/getsgnam.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include - - -#define LOOKUP_TYPE struct sgrp -#define FUNCTION_NAME getsgnam -#define DATABASE_NAME gshadow -#define ADD_PARAMS const char *name -#define ADD_VARIABLES name -#define BUFLEN 1024 - -/* There is no nscd support for the shadow file. */ -#undef USE_NSCD - -#include "../nss/getXXbyYY.c" diff --git a/gshadow/getsgnam_r.c b/gshadow/getsgnam_r.c deleted file mode 100644 index a7bc0b0..0000000 --- a/gshadow/getsgnam_r.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include - - -#define LOOKUP_TYPE struct sgrp -#define FUNCTION_NAME getsgnam -#define DATABASE_NAME gshadow -#define ADD_PARAMS const char *name -#define ADD_VARIABLES name -#define BUFLEN 1024 -#define NO_COMPAT_NEEDED 1 - -/* There is no nscd support for the shadow file. */ -#undef USE_NSCD - -#include "../nss/getXXbyYY_r.c" diff --git a/gshadow/gshadow.h b/gshadow/gshadow.h deleted file mode 100644 index 078e145..0000000 --- a/gshadow/gshadow.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -/* Declaration of types and functions for shadow group suite. */ - -#ifndef _GSHADOW_H -#define _GSHADOW_H 1 - -#include -#include -#include - -#define __need_size_t -#include - -/* Path to the user database files. */ -#define GSHADOW _PATH_GSHADOW - - -__BEGIN_DECLS - -/* Structure of the group file. */ -struct sgrp - { - char *sg_namp; /* Group name. */ - char *sg_passwd; /* Encrypted password. */ - char **sg_adm; /* Group administrator list. */ - char **sg_mem; /* Group member list. */ - }; - - -/* Open database for reading. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern void setsgent (void); - -/* Close database. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern void endsgent (void); - -/* Get next entry from database, perhaps after opening the file. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern struct sgrp *getsgent (void); - -/* Get shadow entry matching NAME. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern struct sgrp *getsgnam (const char *__name); - -/* Read shadow entry from STRING. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern struct sgrp *sgetsgent (const char *__string); - -/* Read next shadow entry from STREAM. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern struct sgrp *fgetsgent (FILE *__stream); - -/* Write line containing shadow password entry to stream. - - This function is not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation it is a cancellation point and - therefore not marked with __THROW. */ -extern int putsgent (const struct sgrp *__g, FILE *__stream); - - -#ifdef __USE_MISC -/* Reentrant versions of some of the functions above. - - These functions are not part of POSIX and therefore no official - cancellation point. But due to similarity with an POSIX interface - or due to the implementation they are cancellation points and - therefore not marked with __THROW. */ -extern int getsgent_r (struct sgrp *__result_buf, char *__buffer, - size_t __buflen, struct sgrp **__result) - __attr_access ((__write_only__, 2, 3)); - -extern int getsgnam_r (const char *__name, struct sgrp *__result_buf, - char *__buffer, size_t __buflen, - struct sgrp **__result) - __attr_access ((__write_only__, 3, 4)); - -extern int sgetsgent_r (const char *__string, struct sgrp *__result_buf, - char *__buffer, size_t __buflen, - struct sgrp **__result) - __attr_access ((__write_only__, 3, 4)); - -extern int fgetsgent_r (FILE *__stream, struct sgrp *__result_buf, - char *__buffer, size_t __buflen, - struct sgrp **__result) - __attr_access ((__write_only__, 3, 4)); -#endif /* misc */ - -__END_DECLS - -#endif /* gshadow.h */ diff --git a/gshadow/putsgent.c b/gshadow/putsgent.c deleted file mode 100644 index cd48eb2..0000000 --- a/gshadow/putsgent.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include -#include -#include -#include -#include - -#define _S(x) x ? x : "" - - -/* Write an entry to the given stream. - This must know the format of the group file. */ -int -putsgent (const struct sgrp *g, FILE *stream) -{ - int errors = 0; - - if (g->sg_namp == NULL || !__nss_valid_field (g->sg_namp) - || !__nss_valid_field (g->sg_passwd) - || !__nss_valid_list_field (g->sg_adm) - || !__nss_valid_list_field (g->sg_mem)) - { - __set_errno (EINVAL); - return -1; - } - - _IO_flockfile (stream); - - if (fprintf (stream, "%s:%s:", g->sg_namp, _S (g->sg_passwd)) < 0) - ++errors; - - bool first = true; - char **sp = g->sg_adm; - if (sp != NULL) - while (*sp != NULL) - { - if (fprintf (stream, "%s%s", first ? "" : ",", *sp++) < 0) - { - ++errors; - break; - } - first = false; - } - if (putc_unlocked (':', stream) == EOF) - ++errors; - - first = true; - sp = g->sg_mem; - if (sp != NULL) - while (*sp != NULL) - { - if (fprintf (stream, "%s%s", first ? "" : ",", *sp++) < 0) - { - ++errors; - break; - } - first = false; - } - if (putc_unlocked ('\n', stream) == EOF) - ++errors; - - _IO_funlockfile (stream); - - return errors ? -1 : 0; -} diff --git a/gshadow/sgetsgent.c b/gshadow/sgetsgent.c deleted file mode 100644 index 92302f7..0000000 --- a/gshadow/sgetsgent.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include -#include -#include -#include - - -/* A reasonable size for a buffer to start with. */ -#define BUFLEN_SPWD 1024 - -/* We need to protect the dynamic buffer handling. */ -__libc_lock_define_initialized (static, lock); - -/* Read one shadow entry from the given stream. */ -struct sgrp * -sgetsgent (const char *string) -{ - static char *buffer; - static size_t buffer_size; - static struct sgrp resbuf; - struct sgrp *result; - int save; - - /* Get lock. */ - __libc_lock_lock (lock); - - /* Allocate buffer if not yet available. */ - if (buffer == NULL) - { - buffer_size = BUFLEN_SPWD; - buffer = malloc (buffer_size); - } - - while (buffer != NULL - && __sgetsgent_r (string, &resbuf, buffer, buffer_size, &result) != 0 - && errno == ERANGE) - { - char *new_buf; - buffer_size += BUFLEN_SPWD; - new_buf = realloc (buffer, buffer_size); - if (new_buf == NULL) - { - /* We are out of memory. Free the current buffer so that the - process gets a chance for a normal termination. */ - save = errno; - free (buffer); - __set_errno (save); - } - buffer = new_buf; - } - - if (buffer == NULL) - result = NULL; - - /* Release lock. Preserve error value. */ - save = errno; - __libc_lock_unlock (lock); - __set_errno (save); - - return result; -} diff --git a/gshadow/sgetsgent_r.c b/gshadow/sgetsgent_r.c deleted file mode 100644 index c75624e..0000000 --- a/gshadow/sgetsgent_r.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2009-2023 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 - . */ - -#include -#include -#include -#include -#include - -/* Define a line parsing function using the common code - used in the nss_files module. */ - -#define STRUCTURE sgrp -#define ENTNAME sgent -struct sgent_data {}; - - -#define TRAILING_LIST_MEMBER sg_mem -#define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',') -#include -LINE_PARSER -(, - STRING_FIELD (result->sg_namp, ISCOLON, 0); - if (line[0] == '\0' - && (result->sg_namp[0] == '+' || result->sg_namp[0] == '-')) - { - result->sg_passwd = NULL; - result->sg_adm = NULL; - result->sg_mem = NULL; - } - else - { - STRING_FIELD (result->sg_passwd, ISCOLON, 0); - STRING_LIST (result->sg_adm, ':'); - } - ) - - -/* Read one shadow entry from the given stream. */ -int -__sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer, - size_t buflen, struct sgrp **result) -{ - char *sp; - if (string < buffer || string >= buffer + buflen) - { - buffer[buflen - 1] = '\0'; - sp = strncpy (buffer, string, buflen); - if (buffer[buflen - 1] != '\0') - { - __set_errno (ERANGE); - return ERANGE; - } - } - else - sp = (char *) string; - - int parse_result = parse_line (sp, resbuf, (void *) buffer, buflen, &errno); - *result = parse_result > 0 ? resbuf : NULL; - - return *result == NULL ? errno : 0; -} -weak_alias (__sgetsgent_r, sgetsgent_r) diff --git a/gshadow/tst-fgetsgent_r.c b/gshadow/tst-fgetsgent_r.c deleted file mode 100644 index 17558fa..0000000 --- a/gshadow/tst-fgetsgent_r.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Test for fgetsgent_r and buffer sizes. - Copyright (C) 2020-2023 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 - . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Turn a parsed struct back into a line string. The returned string - should be freed. */ -static char * -format_ent (const struct sgrp *e) -{ - struct xmemstream stream; - xopen_memstream (&stream); - TEST_COMPARE (putsgent (e, stream.out), 0); - xfclose_memstream (&stream); - return stream.buffer; -} - -/* An entry in the input file along with the expected output. */ -struct input -{ - const char *line; /* Line in the file. */ - const char *expected; /* Expected output. NULL if skipped. */ -}; - -const struct input inputs[] = - { - /* Regular entries. */ - { "g1:x1::\n", "g1:x1::\n" }, - { "g2:x2:a1:\n", "g2:x2:a1:\n" }, - { "g3:x3:a2:u1\n", "g3:x3:a2:u1\n" }, - { "g4:x4:a3,a4:u2,u3,u4\n", "g4:x4:a3,a4:u2,u3,u4\n" }, - - /* Comments and empty lines. */ - { "\n", NULL }, - { " \n", NULL }, - { "\t\n", NULL }, - { "#g:x::\n", NULL }, - { " #g:x::\n", NULL }, - { "\t#g:x::\n", NULL }, - { " \t#g:x::\n", NULL }, - - /* Marker for synchronization. */ - { "g5:x5::\n", "g5:x5::\n" }, - - /* Leading whitespace. */ - { " g6:x6::\n", "g6:x6::\n" }, - { "\tg7:x7::\n", "g7:x7::\n" }, - - /* This is expected to trigger buffer exhaustion during parsing - (bug 20338). */ - { - "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", - "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", - }, - { - "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", - "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", - }, - }; - -/* Writes the test data to a temporary file and returns its name. The - returned pointer should be freed. */ -static char * -create_test_file (void) -{ - char *path; - int fd = create_temp_file ("tst-fgetsgent_r-", &path); - FILE *fp = fdopen (fd, "w"); - TEST_VERIFY_EXIT (fp != NULL); - - for (size_t i = 0; i < array_length (inputs); ++i) - fputs (inputs[i].line, fp); - - xfclose (fp); - return path; -} - -/* Read the test file with the indicated start buffer size. Return - true if the buffer size had to be increased during reading. */ -static bool -run_test (const char *path, size_t buffer_size) -{ - bool resized = false; - FILE *fp = xfopen (path, "r"); - - /* This avoids repeated lseek system calls (bug 26257). */ - TEST_COMPARE (fseeko64 (fp, 0, SEEK_SET), 0); - - size_t i = 0; - while (true) - { - /* Skip over unused expected entries. */ - while (i < array_length (inputs) && inputs[i].expected == NULL) - ++i; - - /* Store the data on the heap, to help valgrind to detect - invalid accesses. */ - struct sgrp *result_storage = xmalloc (sizeof (*result_storage)); - char *buffer = xmalloc (buffer_size); - struct sgrp **result_pointer_storage - = xmalloc (sizeof (*result_pointer_storage)); - - int ret = fgetsgent_r (fp, result_storage, buffer, buffer_size, - result_pointer_storage); - if (ret == 0) - { - TEST_VERIFY (*result_pointer_storage != NULL); - TEST_VERIFY (i < array_length (inputs)); - if (*result_pointer_storage != NULL - && i < array_length (inputs)) - { - char * actual = format_ent (*result_pointer_storage); - TEST_COMPARE_STRING (inputs[i].expected, actual); - free (actual); - ++i; - } - else - break; - } - else - { - TEST_VERIFY (*result_pointer_storage == NULL); - TEST_COMPARE (ret, errno); - - if (ret == ENOENT) - { - TEST_COMPARE (i, array_length (inputs)); - free (result_pointer_storage); - free (buffer); - free (result_storage); - break; - } - else if (ret == ERANGE) - { - resized = true; - ++buffer_size; - } - else - FAIL_EXIT1 ("read failure: %m"); - } - - free (result_pointer_storage); - free (buffer); - free (result_storage); - } - - xfclose (fp); - return resized; -} - -static int -do_test (void) -{ - char *path = create_test_file (); - - for (size_t buffer_size = 3; ; ++buffer_size) - { - bool resized = run_test (path, buffer_size); - if (!resized) - break; - } - - free (path); - - return 0; -} - -#include diff --git a/gshadow/tst-gshadow.c b/gshadow/tst-gshadow.c deleted file mode 100644 index 8b469b7..0000000 --- a/gshadow/tst-gshadow.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include -#include - - -static const struct sgrp data[] = - { - { (char *) "one", (char *) "pwdone", - (char *[]) { (char *) "admoneone", (char *) "admonetwo", - (char *) "admonethree", NULL }, - (char *[]) { (char *) "memoneone", (char *) "memonetwo", - (char *) "memonethree", NULL } }, - { (char *) "two", (char *) "pwdtwo", - (char *[]) { (char *) "admtwoone", (char *) "admtwotwo", NULL }, - (char *[]) { (char *) "memtwoone", (char *) "memtwotwo", - (char *) "memtwothree", NULL } }, - { (char *) "three", (char *) "pwdthree", - (char *[]) { (char *) "admthreeone", (char *) "admthreetwo", NULL }, - (char *[]) { (char *) "memthreeone", (char *) "memthreetwo", NULL } }, - { (char *) "four", (char *) "pwdfour", - (char *[]) { (char *) "admfourone", (char *) "admfourtwo", NULL }, - (char *[]) { NULL } }, - { (char *) "five", (char *) "pwdfive", - (char *[]) { NULL }, - (char *[]) { (char *) "memfiveone", (char *) "memfivetwo", NULL } }, - }; -#define ndata (sizeof (data) / sizeof (data[0])) - - -static int -do_test (void) -{ - FILE *fp = tmpfile (); - if (fp == NULL) - { - puts ("cannot open temporary file"); - return 1; - } - - for (size_t i = 0; i < ndata; ++i) - if (putsgent (&data[i], fp) != 0) - { - printf ("putsgent call %zu failed\n", i + 1); - return 1; - } - - rewind (fp); - - int result = 0; - int seen = -1; - struct sgrp *g; - while ((g = fgetsgent (fp)) != NULL) - { - ++seen; - if (strcmp (g->sg_namp, data[seen].sg_namp) != 0) - { - printf ("sg_namp of entry %d does not match: %s vs %s\n", - seen + 1, g->sg_namp, data[seen].sg_namp); - result = 1; - } - if (strcmp (g->sg_passwd, data[seen].sg_passwd) != 0) - { - printf ("sg_passwd of entry %d does not match: %s vs %s\n", - seen + 1, g->sg_passwd, data[seen].sg_passwd); - result = 1; - } - if (g->sg_adm == NULL) - { - printf ("sg_adm of entry %d is NULL\n", seen + 1); - result = 1; - } - else - { - int i = 1; - char **sp1 = g->sg_adm; - char **sp2 = data[seen].sg_adm; - while (*sp1 != NULL && *sp2 != NULL) - { - if (strcmp (*sp1, *sp2) != 0) - { - printf ("sg_adm[%d] of entry %d does not match: %s vs %s\n", - i, seen + 1, *sp1, *sp2); - result = 1; - } - ++sp1; - ++sp2; - ++i; - } - if (*sp1 == NULL && *sp2 != NULL) - { - printf ("sg_adm of entry %d has too few entries\n", seen + 1); - result = 1; - } - else if (*sp1 != NULL && *sp2 == NULL) - { - printf ("sg_adm of entry %d has too many entries\n", seen + 1); - result = 1; - } - } - if (g->sg_mem == NULL) - { - printf ("sg_mem of entry %d is NULL\n", seen + 1); - result = 1; - } - else - { - int i = 1; - char **sp1 = g->sg_mem; - char **sp2 = data[seen].sg_mem; - while (*sp1 != NULL && *sp2 != NULL) - { - if (strcmp (*sp1, *sp2) != 0) - { - printf ("sg_mem[%d] of entry %d does not match: %s vs %s\n", - i, seen + 1, *sp1, *sp2); - result = 1; - } - ++sp1; - ++sp2; - ++i; - } - if (*sp1 == NULL && *sp2 != NULL) - { - printf ("sg_mem of entry %d has too few entries\n", seen + 1); - result = 1; - } - else if (*sp1 != NULL && *sp2 == NULL) - { - printf ("sg_mem of entry %d has too many entries\n", seen + 1); - result = 1; - } - } - } - - fclose (fp); - - return result; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/gshadow/tst-putsgent.c b/gshadow/tst-putsgent.c deleted file mode 100644 index 2ee0253..0000000 --- a/gshadow/tst-putsgent.c +++ /dev/null @@ -1,168 +0,0 @@ -/* Test for processing of invalid gshadow entries. [BZ #18724] - Copyright (C) 2015-2023 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 - . */ - -#include -#include -#include -#include -#include -#include - -static bool errors; - -static void -check (struct sgrp e, const char *expected) -{ - char *buf; - size_t buf_size; - FILE *f = open_memstream (&buf, &buf_size); - - if (f == NULL) - { - printf ("open_memstream: %m\n"); - errors = true; - return; - } - - int ret = putsgent (&e, f); - - if (expected == NULL) - { - if (ret == -1) - { - if (errno != EINVAL) - { - printf ("putsgent: unexpected error code: %m\n"); - errors = true; - } - } - else - { - printf ("putsgent: unexpected success (\"%s\")\n", e.sg_namp); - errors = true; - } - } - else - { - /* Expect success. */ - size_t expected_length = strlen (expected); - if (ret == 0) - { - long written = ftell (f); - - if (written <= 0 || fflush (f) < 0) - { - printf ("stream error: %m\n"); - errors = true; - } - else if (buf[written - 1] != '\n') - { - printf ("FAILED: \"%s\" without newline\n", expected); - errors = true; - } - else if (strncmp (buf, expected, written - 1) != 0 - || written - 1 != expected_length) - { - printf ("FAILED: \"%s\" (%ld), expected \"%s\" (%zu)\n", - buf, written - 1, expected, expected_length); - errors = true; - } - } - else - { - printf ("FAILED: putsgent (expected \"%s\"): %m\n", expected); - errors = true; - } - } - - fclose (f); - free (buf); -} - -static int -do_test (void) -{ - check ((struct sgrp) { - .sg_namp = (char *) "root", - }, - "root:::"); - check ((struct sgrp) { - .sg_namp = (char *) "root", - .sg_passwd = (char *) "password", - }, - "root:password::"); - check ((struct sgrp) { - .sg_namp = (char *) "root", - .sg_passwd = (char *) "password", - .sg_adm = (char *[]) {(char *) "adm1", (char *) "adm2", NULL}, - .sg_mem = (char *[]) {(char *) "mem1", (char *) "mem2", NULL}, - }, - "root:password:adm1,adm2:mem1,mem2"); - - /* Bad values. */ - { - static const char *const bad_strings[] = { - ":", - "\n", - ":bad", - "\nbad", - "b:ad", - "b\nad", - "bad:", - "bad\n", - "b:a\nd", - ",", - "\n,", - ":,", - ",bad", - "b,ad", - "bad,", - NULL - }; - for (const char *const *bad = bad_strings; *bad != NULL; ++bad) - { - char *members[] - = {(char *) "first", (char *) *bad, (char *) "last", NULL}; - if (strpbrk (*bad, ":\n") != NULL) - { - check ((struct sgrp) { - .sg_namp = (char *) *bad, - }, NULL); - check ((struct sgrp) { - .sg_namp = (char *) "root", - .sg_passwd = (char *) *bad, - }, NULL); - } - check ((struct sgrp) { - .sg_namp = (char *) "root", - .sg_passwd = (char *) "password", - .sg_adm = members - }, NULL); - check ((struct sgrp) { - .sg_namp = (char *) "root", - .sg_passwd = (char *) "password", - .sg_mem = members - }, NULL); - } - } - - return errors; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/gshadow/tst-sgetsgent.c b/gshadow/tst-sgetsgent.c deleted file mode 100644 index 0370c10..0000000 --- a/gshadow/tst-sgetsgent.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Test large input for sgetsgent (bug 30151). - Copyright (C) 2023 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 - . */ - -#include -#include -#include -#include -#include -#include - -static int -do_test (void) -{ - /* Create a shadow group with 1000 members. */ - struct xmemstream mem; - xopen_memstream (&mem); - const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ"; - fprintf (mem.out, "group-name:%s::m0", passwd); - for (int i = 1; i < 1000; ++i) - fprintf (mem.out, ",m%d", i); - xfclose_memstream (&mem); - - /* Call sgetsgent. */ - char *input = mem.buffer; - struct sgrp *e = sgetsgent (input); - TEST_VERIFY_EXIT (e != NULL); - TEST_COMPARE_STRING (e->sg_namp, "group-name"); - TEST_COMPARE_STRING (e->sg_passwd, passwd); - /* No administrators. */ - TEST_COMPARE_STRING (e->sg_adm[0], NULL); - /* Check the members list. */ - for (int i = 0; i < 1000; ++i) - { - char *member = xasprintf ("m%d", i); - TEST_COMPARE_STRING (e->sg_mem[i], member); - free (member); - } - TEST_COMPARE_STRING (e->sg_mem[1000], NULL); - - /* Check that putsgent brings back the input string. */ - xopen_memstream (&mem); - TEST_COMPARE (putsgent (e, mem.out), 0); - xfclose_memstream (&mem); - /* Compare without the trailing '\n' that putsgent added. */ - TEST_COMPARE (mem.buffer[mem.length - 1], '\n'); - mem.buffer[mem.length - 1] = '\0'; - TEST_COMPARE_STRING (mem.buffer, input); - - free (mem.buffer); - free (input); - return 0; -} - -#include diff --git a/include/gshadow.h b/include/gshadow.h index 1cefcfc..95f8f95 100644 --- a/include/gshadow.h +++ b/include/gshadow.h @@ -1,5 +1,5 @@ #ifndef _GSHADOW_H -#include +#include # ifndef _ISOMAC diff --git a/nss/Makefile b/nss/Makefile index baf7d9d..5256b90 100644 --- a/nss/Makefile +++ b/nss/Makefile @@ -24,6 +24,7 @@ include ../Makeconfig headers := \ grp.h \ + gshadow.h \ nss.h \ # headers @@ -79,6 +80,29 @@ CFLAGS-initgroups.c += -fexceptions CFLAGS-putgrent.c += -fexceptions $(libio-mtsafe) endif +# gshadow routines: +routines += \ + fgetsgent \ + fgetsgent_r \ + getsgent \ + getsgent_r \ + getsgnam \ + getsgnam_r \ + putsgent \ + sgetsgent \ + sgetsgent_r \ + # routines + +ifeq ($(have-thread-library),yes) +CFLAGS-getsgent_r.c += -fexceptions +CFLAGS-getsgent.c += -fexceptions +CFLAGS-fgetsgent.c += -fexceptions +CFLAGS-fgetsgent_r.c += -fexceptions $(libio-mtsafe) +CFLAGS-putsgent.c += -fexceptions $(libio-mtsafe) +CFLAGS-getsgnam.c += -fexceptions +CFLAGS-getsgnam_r.c += -fexceptions +endif + # These are the databases that go through nss dispatch. # Caution: if you add a database here, you must add its real name # in databases.def, too. @@ -118,6 +142,8 @@ tests := \ test-digits-dots \ test-netdb \ testgrp \ + tst-fgetsgent_r \ + tst-gshadow \ tst-nss-getpwent \ tst-nss-hash \ tst-nss-test1 \ @@ -126,6 +152,8 @@ tests := \ tst-nss-test5 \ tst-nss-test_errno \ tst-putgrent \ + tst-putsgent \ + tst-sgetsgent \ # tests xtests = bug-erange diff --git a/nss/Versions b/nss/Versions index 5401829..6204ac0 100644 --- a/nss/Versions +++ b/nss/Versions @@ -37,6 +37,25 @@ libc { # g* getgrouplist; } + GLIBC_2.10 { + # e* + endsgent; + + # f* + fgetsgent; fgetsgent_r; + + # g* + getsgent; getsgent_r; getsgnam; getsgnam_r; + + # p* + putsgent; + + # s* + setsgent; + + # s* + sgetsgent; sgetsgent_r; + } GLIBC_2.27 { } GLIBC_PRIVATE { diff --git a/nss/fgetsgent.c b/nss/fgetsgent.c new file mode 100644 index 0000000..dc26b24 --- /dev/null +++ b/nss/fgetsgent.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include +#include +#include +#include +#include +#include + + +/* A reasonable size for a buffer to start with. */ +#define BUFLEN_SPWD 1024 + +/* We need to protect the dynamic buffer handling. */ +__libc_lock_define_initialized (static, lock); + +static char *buffer; + +/* Read one shadow entry from the given stream. */ +struct sgrp * +fgetsgent (FILE *stream) +{ + static size_t buffer_size; + static struct sgrp resbuf; + fpos_t pos; + struct sgrp *result; + int save; + + if (fgetpos (stream, &pos) != 0) + return NULL; + + /* Get lock. */ + __libc_lock_lock (lock); + + /* Allocate buffer if not yet available. */ + if (buffer == NULL) + { + buffer_size = BUFLEN_SPWD; + buffer = malloc (buffer_size); + } + + while (buffer != NULL + && (__fgetsgent_r (stream, &resbuf, buffer, buffer_size, &result) + == ERANGE)) + { + char *new_buf; + buffer_size += BUFLEN_SPWD; + new_buf = realloc (buffer, buffer_size); + if (new_buf == NULL) + { + /* We are out of memory. Free the current buffer so that the + process gets a chance for a normal termination. */ + save = errno; + free (buffer); + __set_errno (save); + } + buffer = new_buf; + + /* Reset the stream. */ + if (fsetpos (stream, &pos) != 0) + buffer = NULL; + } + + if (buffer == NULL) + result = NULL; + + /* Release lock. Preserve error value. */ + save = errno; + __libc_lock_unlock (lock); + __set_errno (save); + + return result; +} + +weak_alias (buffer, __libc_fgetsgent_freeres_ptr); diff --git a/nss/fgetsgent_r.c b/nss/fgetsgent_r.c new file mode 100644 index 0000000..54616b9 --- /dev/null +++ b/nss/fgetsgent_r.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include +#include +#include +#include + +/* Define a line parsing function using the common code + used in the nss_files module. */ + +#define STRUCTURE sgrp +#define ENTNAME sgent +#define EXTERN_PARSER 1 +struct sgent_data {}; + +#include + + +/* Read one shadow entry from the given stream. */ +int +__fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, + struct sgrp **result) +{ + int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); + if (ret == 0) + *result = resbuf; + else + *result = NULL; + return ret; +} +weak_alias (__fgetsgent_r, fgetsgent_r) diff --git a/nss/getsgent.c b/nss/getsgent.c new file mode 100644 index 0000000..68f67c0 --- /dev/null +++ b/nss/getsgent.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include + + +#define LOOKUP_TYPE struct sgrp +#define SETFUNC_NAME setsgent +#define GETFUNC_NAME getsgent +#define ENDFUNC_NAME endsgent +#define DATABASE_NAME gshadow +#define BUFLEN 1024 + +/* There is no nscd support for the shadow file. */ +#undef USE_NSCD + +#include "../nss/getXXent.c" diff --git a/nss/getsgent_r.c b/nss/getsgent_r.c new file mode 100644 index 0000000..b24ebe1 --- /dev/null +++ b/nss/getsgent_r.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include + + +#define LOOKUP_TYPE struct sgrp +#define SETFUNC_NAME setsgent +#define GETFUNC_NAME getsgent +#define ENDFUNC_NAME endsgent +#define DATABASE_NAME gshadow +#define BUFLEN 1024 +#define NO_COMPAT_NEEDED 1 + +/* There is no nscd support for the shadow file. */ +#undef USE_NSCD + +#include "../nss/getXXent_r.c" diff --git a/nss/getsgnam.c b/nss/getsgnam.c new file mode 100644 index 0000000..3177c86 --- /dev/null +++ b/nss/getsgnam.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include + + +#define LOOKUP_TYPE struct sgrp +#define FUNCTION_NAME getsgnam +#define DATABASE_NAME gshadow +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name +#define BUFLEN 1024 + +/* There is no nscd support for the shadow file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY.c" diff --git a/nss/getsgnam_r.c b/nss/getsgnam_r.c new file mode 100644 index 0000000..a7bc0b0 --- /dev/null +++ b/nss/getsgnam_r.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include + + +#define LOOKUP_TYPE struct sgrp +#define FUNCTION_NAME getsgnam +#define DATABASE_NAME gshadow +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name +#define BUFLEN 1024 +#define NO_COMPAT_NEEDED 1 + +/* There is no nscd support for the shadow file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY_r.c" diff --git a/nss/gshadow.h b/nss/gshadow.h new file mode 100644 index 0000000..078e145 --- /dev/null +++ b/nss/gshadow.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2009-2023 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 + . */ + +/* Declaration of types and functions for shadow group suite. */ + +#ifndef _GSHADOW_H +#define _GSHADOW_H 1 + +#include +#include +#include + +#define __need_size_t +#include + +/* Path to the user database files. */ +#define GSHADOW _PATH_GSHADOW + + +__BEGIN_DECLS + +/* Structure of the group file. */ +struct sgrp + { + char *sg_namp; /* Group name. */ + char *sg_passwd; /* Encrypted password. */ + char **sg_adm; /* Group administrator list. */ + char **sg_mem; /* Group member list. */ + }; + + +/* Open database for reading. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void setsgent (void); + +/* Close database. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endsgent (void); + +/* Get next entry from database, perhaps after opening the file. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct sgrp *getsgent (void); + +/* Get shadow entry matching NAME. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct sgrp *getsgnam (const char *__name); + +/* Read shadow entry from STRING. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct sgrp *sgetsgent (const char *__string); + +/* Read next shadow entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct sgrp *fgetsgent (FILE *__stream); + +/* Write line containing shadow password entry to stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putsgent (const struct sgrp *__g, FILE *__stream); + + +#ifdef __USE_MISC +/* Reentrant versions of some of the functions above. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getsgent_r (struct sgrp *__result_buf, char *__buffer, + size_t __buflen, struct sgrp **__result) + __attr_access ((__write_only__, 2, 3)); + +extern int getsgnam_r (const char *__name, struct sgrp *__result_buf, + char *__buffer, size_t __buflen, + struct sgrp **__result) + __attr_access ((__write_only__, 3, 4)); + +extern int sgetsgent_r (const char *__string, struct sgrp *__result_buf, + char *__buffer, size_t __buflen, + struct sgrp **__result) + __attr_access ((__write_only__, 3, 4)); + +extern int fgetsgent_r (FILE *__stream, struct sgrp *__result_buf, + char *__buffer, size_t __buflen, + struct sgrp **__result) + __attr_access ((__write_only__, 3, 4)); +#endif /* misc */ + +__END_DECLS + +#endif /* gshadow.h */ diff --git a/nss/putsgent.c b/nss/putsgent.c new file mode 100644 index 0000000..cd48eb2 --- /dev/null +++ b/nss/putsgent.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include +#include +#include +#include +#include + +#define _S(x) x ? x : "" + + +/* Write an entry to the given stream. + This must know the format of the group file. */ +int +putsgent (const struct sgrp *g, FILE *stream) +{ + int errors = 0; + + if (g->sg_namp == NULL || !__nss_valid_field (g->sg_namp) + || !__nss_valid_field (g->sg_passwd) + || !__nss_valid_list_field (g->sg_adm) + || !__nss_valid_list_field (g->sg_mem)) + { + __set_errno (EINVAL); + return -1; + } + + _IO_flockfile (stream); + + if (fprintf (stream, "%s:%s:", g->sg_namp, _S (g->sg_passwd)) < 0) + ++errors; + + bool first = true; + char **sp = g->sg_adm; + if (sp != NULL) + while (*sp != NULL) + { + if (fprintf (stream, "%s%s", first ? "" : ",", *sp++) < 0) + { + ++errors; + break; + } + first = false; + } + if (putc_unlocked (':', stream) == EOF) + ++errors; + + first = true; + sp = g->sg_mem; + if (sp != NULL) + while (*sp != NULL) + { + if (fprintf (stream, "%s%s", first ? "" : ",", *sp++) < 0) + { + ++errors; + break; + } + first = false; + } + if (putc_unlocked ('\n', stream) == EOF) + ++errors; + + _IO_funlockfile (stream); + + return errors ? -1 : 0; +} diff --git a/nss/sgetsgent.c b/nss/sgetsgent.c new file mode 100644 index 0000000..92302f7 --- /dev/null +++ b/nss/sgetsgent.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include +#include +#include +#include + + +/* A reasonable size for a buffer to start with. */ +#define BUFLEN_SPWD 1024 + +/* We need to protect the dynamic buffer handling. */ +__libc_lock_define_initialized (static, lock); + +/* Read one shadow entry from the given stream. */ +struct sgrp * +sgetsgent (const char *string) +{ + static char *buffer; + static size_t buffer_size; + static struct sgrp resbuf; + struct sgrp *result; + int save; + + /* Get lock. */ + __libc_lock_lock (lock); + + /* Allocate buffer if not yet available. */ + if (buffer == NULL) + { + buffer_size = BUFLEN_SPWD; + buffer = malloc (buffer_size); + } + + while (buffer != NULL + && __sgetsgent_r (string, &resbuf, buffer, buffer_size, &result) != 0 + && errno == ERANGE) + { + char *new_buf; + buffer_size += BUFLEN_SPWD; + new_buf = realloc (buffer, buffer_size); + if (new_buf == NULL) + { + /* We are out of memory. Free the current buffer so that the + process gets a chance for a normal termination. */ + save = errno; + free (buffer); + __set_errno (save); + } + buffer = new_buf; + } + + if (buffer == NULL) + result = NULL; + + /* Release lock. Preserve error value. */ + save = errno; + __libc_lock_unlock (lock); + __set_errno (save); + + return result; +} diff --git a/nss/sgetsgent_r.c b/nss/sgetsgent_r.c new file mode 100644 index 0000000..c75624e --- /dev/null +++ b/nss/sgetsgent_r.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2009-2023 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 + . */ + +#include +#include +#include +#include +#include + +/* Define a line parsing function using the common code + used in the nss_files module. */ + +#define STRUCTURE sgrp +#define ENTNAME sgent +struct sgent_data {}; + + +#define TRAILING_LIST_MEMBER sg_mem +#define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',') +#include +LINE_PARSER +(, + STRING_FIELD (result->sg_namp, ISCOLON, 0); + if (line[0] == '\0' + && (result->sg_namp[0] == '+' || result->sg_namp[0] == '-')) + { + result->sg_passwd = NULL; + result->sg_adm = NULL; + result->sg_mem = NULL; + } + else + { + STRING_FIELD (result->sg_passwd, ISCOLON, 0); + STRING_LIST (result->sg_adm, ':'); + } + ) + + +/* Read one shadow entry from the given stream. */ +int +__sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer, + size_t buflen, struct sgrp **result) +{ + char *sp; + if (string < buffer || string >= buffer + buflen) + { + buffer[buflen - 1] = '\0'; + sp = strncpy (buffer, string, buflen); + if (buffer[buflen - 1] != '\0') + { + __set_errno (ERANGE); + return ERANGE; + } + } + else + sp = (char *) string; + + int parse_result = parse_line (sp, resbuf, (void *) buffer, buflen, &errno); + *result = parse_result > 0 ? resbuf : NULL; + + return *result == NULL ? errno : 0; +} +weak_alias (__sgetsgent_r, sgetsgent_r) diff --git a/nss/tst-fgetsgent_r.c b/nss/tst-fgetsgent_r.c new file mode 100644 index 0000000..17558fa --- /dev/null +++ b/nss/tst-fgetsgent_r.c @@ -0,0 +1,192 @@ +/* Test for fgetsgent_r and buffer sizes. + Copyright (C) 2020-2023 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Turn a parsed struct back into a line string. The returned string + should be freed. */ +static char * +format_ent (const struct sgrp *e) +{ + struct xmemstream stream; + xopen_memstream (&stream); + TEST_COMPARE (putsgent (e, stream.out), 0); + xfclose_memstream (&stream); + return stream.buffer; +} + +/* An entry in the input file along with the expected output. */ +struct input +{ + const char *line; /* Line in the file. */ + const char *expected; /* Expected output. NULL if skipped. */ +}; + +const struct input inputs[] = + { + /* Regular entries. */ + { "g1:x1::\n", "g1:x1::\n" }, + { "g2:x2:a1:\n", "g2:x2:a1:\n" }, + { "g3:x3:a2:u1\n", "g3:x3:a2:u1\n" }, + { "g4:x4:a3,a4:u2,u3,u4\n", "g4:x4:a3,a4:u2,u3,u4\n" }, + + /* Comments and empty lines. */ + { "\n", NULL }, + { " \n", NULL }, + { "\t\n", NULL }, + { "#g:x::\n", NULL }, + { " #g:x::\n", NULL }, + { "\t#g:x::\n", NULL }, + { " \t#g:x::\n", NULL }, + + /* Marker for synchronization. */ + { "g5:x5::\n", "g5:x5::\n" }, + + /* Leading whitespace. */ + { " g6:x6::\n", "g6:x6::\n" }, + { "\tg7:x7::\n", "g7:x7::\n" }, + + /* This is expected to trigger buffer exhaustion during parsing + (bug 20338). */ + { + "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", + "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", + }, + { + "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", + "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", + }, + }; + +/* Writes the test data to a temporary file and returns its name. The + returned pointer should be freed. */ +static char * +create_test_file (void) +{ + char *path; + int fd = create_temp_file ("tst-fgetsgent_r-", &path); + FILE *fp = fdopen (fd, "w"); + TEST_VERIFY_EXIT (fp != NULL); + + for (size_t i = 0; i < array_length (inputs); ++i) + fputs (inputs[i].line, fp); + + xfclose (fp); + return path; +} + +/* Read the test file with the indicated start buffer size. Return + true if the buffer size had to be increased during reading. */ +static bool +run_test (const char *path, size_t buffer_size) +{ + bool resized = false; + FILE *fp = xfopen (path, "r"); + + /* This avoids repeated lseek system calls (bug 26257). */ + TEST_COMPARE (fseeko64 (fp, 0, SEEK_SET), 0); + + size_t i = 0; + while (true) + { + /* Skip over unused expected entries. */ + while (i < array_length (inputs) && inputs[i].expected == NULL) + ++i; + + /* Store the data on the heap, to help valgrind to detect + invalid accesses. */ + struct sgrp *result_storage = xmalloc (sizeof (*result_storage)); + char *buffer = xmalloc (buffer_size); + struct sgrp **result_pointer_storage + = xmalloc (sizeof (*result_pointer_storage)); + + int ret = fgetsgent_r (fp, result_storage, buffer, buffer_size, + result_pointer_storage); + if (ret == 0) + { + TEST_VERIFY (*result_pointer_storage != NULL); + TEST_VERIFY (i < array_length (inputs)); + if (*result_pointer_storage != NULL + && i < array_length (inputs)) + { + char * actual = format_ent (*result_pointer_storage); + TEST_COMPARE_STRING (inputs[i].expected, actual); + free (actual); + ++i; + } + else + break; + } + else + { + TEST_VERIFY (*result_pointer_storage == NULL); + TEST_COMPARE (ret, errno); + + if (ret == ENOENT) + { + TEST_COMPARE (i, array_length (inputs)); + free (result_pointer_storage); + free (buffer); + free (result_storage); + break; + } + else if (ret == ERANGE) + { + resized = true; + ++buffer_size; + } + else + FAIL_EXIT1 ("read failure: %m"); + } + + free (result_pointer_storage); + free (buffer); + free (result_storage); + } + + xfclose (fp); + return resized; +} + +static int +do_test (void) +{ + char *path = create_test_file (); + + for (size_t buffer_size = 3; ; ++buffer_size) + { + bool resized = run_test (path, buffer_size); + if (!resized) + break; + } + + free (path); + + return 0; +} + +#include diff --git a/nss/tst-gshadow.c b/nss/tst-gshadow.c new file mode 100644 index 0000000..8b469b7 --- /dev/null +++ b/nss/tst-gshadow.c @@ -0,0 +1,141 @@ +#include +#include +#include + + +static const struct sgrp data[] = + { + { (char *) "one", (char *) "pwdone", + (char *[]) { (char *) "admoneone", (char *) "admonetwo", + (char *) "admonethree", NULL }, + (char *[]) { (char *) "memoneone", (char *) "memonetwo", + (char *) "memonethree", NULL } }, + { (char *) "two", (char *) "pwdtwo", + (char *[]) { (char *) "admtwoone", (char *) "admtwotwo", NULL }, + (char *[]) { (char *) "memtwoone", (char *) "memtwotwo", + (char *) "memtwothree", NULL } }, + { (char *) "three", (char *) "pwdthree", + (char *[]) { (char *) "admthreeone", (char *) "admthreetwo", NULL }, + (char *[]) { (char *) "memthreeone", (char *) "memthreetwo", NULL } }, + { (char *) "four", (char *) "pwdfour", + (char *[]) { (char *) "admfourone", (char *) "admfourtwo", NULL }, + (char *[]) { NULL } }, + { (char *) "five", (char *) "pwdfive", + (char *[]) { NULL }, + (char *[]) { (char *) "memfiveone", (char *) "memfivetwo", NULL } }, + }; +#define ndata (sizeof (data) / sizeof (data[0])) + + +static int +do_test (void) +{ + FILE *fp = tmpfile (); + if (fp == NULL) + { + puts ("cannot open temporary file"); + return 1; + } + + for (size_t i = 0; i < ndata; ++i) + if (putsgent (&data[i], fp) != 0) + { + printf ("putsgent call %zu failed\n", i + 1); + return 1; + } + + rewind (fp); + + int result = 0; + int seen = -1; + struct sgrp *g; + while ((g = fgetsgent (fp)) != NULL) + { + ++seen; + if (strcmp (g->sg_namp, data[seen].sg_namp) != 0) + { + printf ("sg_namp of entry %d does not match: %s vs %s\n", + seen + 1, g->sg_namp, data[seen].sg_namp); + result = 1; + } + if (strcmp (g->sg_passwd, data[seen].sg_passwd) != 0) + { + printf ("sg_passwd of entry %d does not match: %s vs %s\n", + seen + 1, g->sg_passwd, data[seen].sg_passwd); + result = 1; + } + if (g->sg_adm == NULL) + { + printf ("sg_adm of entry %d is NULL\n", seen + 1); + result = 1; + } + else + { + int i = 1; + char **sp1 = g->sg_adm; + char **sp2 = data[seen].sg_adm; + while (*sp1 != NULL && *sp2 != NULL) + { + if (strcmp (*sp1, *sp2) != 0) + { + printf ("sg_adm[%d] of entry %d does not match: %s vs %s\n", + i, seen + 1, *sp1, *sp2); + result = 1; + } + ++sp1; + ++sp2; + ++i; + } + if (*sp1 == NULL && *sp2 != NULL) + { + printf ("sg_adm of entry %d has too few entries\n", seen + 1); + result = 1; + } + else if (*sp1 != NULL && *sp2 == NULL) + { + printf ("sg_adm of entry %d has too many entries\n", seen + 1); + result = 1; + } + } + if (g->sg_mem == NULL) + { + printf ("sg_mem of entry %d is NULL\n", seen + 1); + result = 1; + } + else + { + int i = 1; + char **sp1 = g->sg_mem; + char **sp2 = data[seen].sg_mem; + while (*sp1 != NULL && *sp2 != NULL) + { + if (strcmp (*sp1, *sp2) != 0) + { + printf ("sg_mem[%d] of entry %d does not match: %s vs %s\n", + i, seen + 1, *sp1, *sp2); + result = 1; + } + ++sp1; + ++sp2; + ++i; + } + if (*sp1 == NULL && *sp2 != NULL) + { + printf ("sg_mem of entry %d has too few entries\n", seen + 1); + result = 1; + } + else if (*sp1 != NULL && *sp2 == NULL) + { + printf ("sg_mem of entry %d has too many entries\n", seen + 1); + result = 1; + } + } + } + + fclose (fp); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nss/tst-putsgent.c b/nss/tst-putsgent.c new file mode 100644 index 0000000..2ee0253 --- /dev/null +++ b/nss/tst-putsgent.c @@ -0,0 +1,168 @@ +/* Test for processing of invalid gshadow entries. [BZ #18724] + Copyright (C) 2015-2023 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 + . */ + +#include +#include +#include +#include +#include +#include + +static bool errors; + +static void +check (struct sgrp e, const char *expected) +{ + char *buf; + size_t buf_size; + FILE *f = open_memstream (&buf, &buf_size); + + if (f == NULL) + { + printf ("open_memstream: %m\n"); + errors = true; + return; + } + + int ret = putsgent (&e, f); + + if (expected == NULL) + { + if (ret == -1) + { + if (errno != EINVAL) + { + printf ("putsgent: unexpected error code: %m\n"); + errors = true; + } + } + else + { + printf ("putsgent: unexpected success (\"%s\")\n", e.sg_namp); + errors = true; + } + } + else + { + /* Expect success. */ + size_t expected_length = strlen (expected); + if (ret == 0) + { + long written = ftell (f); + + if (written <= 0 || fflush (f) < 0) + { + printf ("stream error: %m\n"); + errors = true; + } + else if (buf[written - 1] != '\n') + { + printf ("FAILED: \"%s\" without newline\n", expected); + errors = true; + } + else if (strncmp (buf, expected, written - 1) != 0 + || written - 1 != expected_length) + { + printf ("FAILED: \"%s\" (%ld), expected \"%s\" (%zu)\n", + buf, written - 1, expected, expected_length); + errors = true; + } + } + else + { + printf ("FAILED: putsgent (expected \"%s\"): %m\n", expected); + errors = true; + } + } + + fclose (f); + free (buf); +} + +static int +do_test (void) +{ + check ((struct sgrp) { + .sg_namp = (char *) "root", + }, + "root:::"); + check ((struct sgrp) { + .sg_namp = (char *) "root", + .sg_passwd = (char *) "password", + }, + "root:password::"); + check ((struct sgrp) { + .sg_namp = (char *) "root", + .sg_passwd = (char *) "password", + .sg_adm = (char *[]) {(char *) "adm1", (char *) "adm2", NULL}, + .sg_mem = (char *[]) {(char *) "mem1", (char *) "mem2", NULL}, + }, + "root:password:adm1,adm2:mem1,mem2"); + + /* Bad values. */ + { + static const char *const bad_strings[] = { + ":", + "\n", + ":bad", + "\nbad", + "b:ad", + "b\nad", + "bad:", + "bad\n", + "b:a\nd", + ",", + "\n,", + ":,", + ",bad", + "b,ad", + "bad,", + NULL + }; + for (const char *const *bad = bad_strings; *bad != NULL; ++bad) + { + char *members[] + = {(char *) "first", (char *) *bad, (char *) "last", NULL}; + if (strpbrk (*bad, ":\n") != NULL) + { + check ((struct sgrp) { + .sg_namp = (char *) *bad, + }, NULL); + check ((struct sgrp) { + .sg_namp = (char *) "root", + .sg_passwd = (char *) *bad, + }, NULL); + } + check ((struct sgrp) { + .sg_namp = (char *) "root", + .sg_passwd = (char *) "password", + .sg_adm = members + }, NULL); + check ((struct sgrp) { + .sg_namp = (char *) "root", + .sg_passwd = (char *) "password", + .sg_mem = members + }, NULL); + } + } + + return errors; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nss/tst-sgetsgent.c b/nss/tst-sgetsgent.c new file mode 100644 index 0000000..0370c10 --- /dev/null +++ b/nss/tst-sgetsgent.c @@ -0,0 +1,69 @@ +/* Test large input for sgetsgent (bug 30151). + Copyright (C) 2023 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 + . */ + +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + /* Create a shadow group with 1000 members. */ + struct xmemstream mem; + xopen_memstream (&mem); + const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ"; + fprintf (mem.out, "group-name:%s::m0", passwd); + for (int i = 1; i < 1000; ++i) + fprintf (mem.out, ",m%d", i); + xfclose_memstream (&mem); + + /* Call sgetsgent. */ + char *input = mem.buffer; + struct sgrp *e = sgetsgent (input); + TEST_VERIFY_EXIT (e != NULL); + TEST_COMPARE_STRING (e->sg_namp, "group-name"); + TEST_COMPARE_STRING (e->sg_passwd, passwd); + /* No administrators. */ + TEST_COMPARE_STRING (e->sg_adm[0], NULL); + /* Check the members list. */ + for (int i = 0; i < 1000; ++i) + { + char *member = xasprintf ("m%d", i); + TEST_COMPARE_STRING (e->sg_mem[i], member); + free (member); + } + TEST_COMPARE_STRING (e->sg_mem[1000], NULL); + + /* Check that putsgent brings back the input string. */ + xopen_memstream (&mem); + TEST_COMPARE (putsgent (e, mem.out), 0); + xfclose_memstream (&mem); + /* Compare without the trailing '\n' that putsgent added. */ + TEST_COMPARE (mem.buffer[mem.length - 1], '\n'); + mem.buffer[mem.length - 1] = '\0'; + TEST_COMPARE_STRING (mem.buffer, input); + + free (mem.buffer); + free (input); + return 0; +} + +#include -- cgit v1.1