Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nss_wrapper for openSUSE:Factory checked in at 2023-01-26 13:57:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nss_wrapper (Old) and /work/SRC/openSUSE:Factory/.nss_wrapper.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nss_wrapper" Thu Jan 26 13:57:02 2023 rev:16 rq:1060964 version:1.1.15 Changes: -------- --- /work/SRC/openSUSE:Factory/nss_wrapper/nss_wrapper.changes 2022-11-10 14:19:13.741320084 +0100 +++ /work/SRC/openSUSE:Factory/.nss_wrapper.new.32243/nss_wrapper.changes 2023-01-26 14:04:29.726247774 +0100 @@ -1,0 +2,15 @@ +Wed Jan 25 15:45:26 UTC 2023 - Andreas Schneider <[email protected]> + +- Update to version 1.1.15 + * Fixed linking issue in tests + * Fixed a memory leak in tests + +------------------------------------------------------------------- +Wed Jan 25 11:13:12 UTC 2023 - Andreas Schneider <[email protected]> + +- Update to version 1.1.14 + * Fixed implementation of initgroups() + * Fixed implementation of getgrouplist() + * Avoid dclose(RTLD_NEXT) + +------------------------------------------------------------------- Old: ---- nss_wrapper-1.1.13.tar.gz nss_wrapper-1.1.13.tar.gz.asc New: ---- nss_wrapper-1.1.15.tar.gz nss_wrapper-1.1.15.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nss_wrapper.spec ++++++ --- /var/tmp/diff_new_pack.9zP28N/_old 2023-01-26 14:04:30.182250213 +0100 +++ /var/tmp/diff_new_pack.9zP28N/_new 2023-01-26 14:04:30.186250235 +0100 @@ -1,7 +1,7 @@ # # spec file for package nss_wrapper # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -23,7 +23,7 @@ # ############################# NOTE ################################## Name: nss_wrapper -Version: 1.1.13 +Version: 1.1.15 Release: 0 Summary: A wrapper for the user, group and hosts NSS API License: BSD-3-Clause ++++++ nss_wrapper-1.1.13.tar.gz -> nss_wrapper-1.1.15.tar.gz ++++++ Binary files old/nss_wrapper-1.1.13/.cache/clangd/index/nss_nwrap.c.6CD8D6240BEF45A7.idx and new/nss_wrapper-1.1.15/.cache/clangd/index/nss_nwrap.c.6CD8D6240BEF45A7.idx differ Binary files old/nss_wrapper-1.1.13/.cache/clangd/index/nss_utils.c.D245051A87648149.idx and new/nss_wrapper-1.1.15/.cache/clangd/index/nss_utils.c.D245051A87648149.idx differ Binary files old/nss_wrapper-1.1.13/.cache/clangd/index/nss_utils.h.BFE4622C993130F2.idx and new/nss_wrapper-1.1.15/.cache/clangd/index/nss_utils.h.BFE4622C993130F2.idx differ Binary files old/nss_wrapper-1.1.13/.cache/clangd/index/nss_wrapper.c.496306141B70693D.idx and new/nss_wrapper-1.1.15/.cache/clangd/index/nss_wrapper.c.496306141B70693D.idx differ Binary files old/nss_wrapper-1.1.13/.cache/clangd/index/test_initgroups.c.96654DF285FBEEBF.idx and new/nss_wrapper-1.1.15/.cache/clangd/index/test_initgroups.c.96654DF285FBEEBF.idx differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/.clang-format new/nss_wrapper-1.1.15/.clang-format --- old/nss_wrapper-1.1.13/.clang-format 1970-01-01 01:00:00.000000000 +0100 +++ new/nss_wrapper-1.1.15/.clang-format 2023-01-25 12:09:01.000000000 +0100 @@ -0,0 +1,26 @@ +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: LLVM +IndentWidth: 8 +ContinuationIndentWidth: 8 +UseTab: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterEnum: false + AfterFunction: true + AfterStruct: false + AfterUnion: false + AfterExternBlock: true + BeforeElse: false + BeforeWhile: false +AllowShortIfStatementsOnASingleLine: false +ColumnLimit: 80 +IndentCaseLabels: false +AlignAfterOpenBracket: Align +BinPackParameters: false +BinPackArguments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowAllArgumentsOnNextLine: false +AllowShortFunctionsOnASingleLine: Empty +AlwaysBreakAfterReturnType: None +AlignEscapedNewlines: Left +SortIncludes: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/CHANGELOG new/nss_wrapper-1.1.15/CHANGELOG --- old/nss_wrapper-1.1.13/CHANGELOG 2022-11-09 07:45:15.000000000 +0100 +++ new/nss_wrapper-1.1.15/CHANGELOG 2023-01-25 16:41:17.000000000 +0100 @@ -1,6 +1,15 @@ ChangeLog ========== +version 1.1.15 (released 2023-01-25) + * Fixed linking issue in tests + * Fixed a memory leak in tests + +version 1.1.14 (released 2023-01-25) + * Fixed implementation of initgroups() + * Fixed implementation of getgrouplist() + * Avoid dclose(RTLD_NEXT) + version 1.1.13 (released 2022-10-09) * Fixed possible mutex and threading issues diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/CMakeLists.txt new/nss_wrapper-1.1.15/CMakeLists.txt --- old/nss_wrapper-1.1.13/CMakeLists.txt 2022-11-09 07:45:15.000000000 +0100 +++ new/nss_wrapper-1.1.15/CMakeLists.txt 2023-01-25 16:41:17.000000000 +0100 @@ -11,7 +11,7 @@ include(DefineCMakeDefaults) include(DefineCompilerFlags) -project(nss_wrapper VERSION 1.1.13 LANGUAGES C) +project(nss_wrapper VERSION 1.1.15 LANGUAGES C) # global needed variables set(APPLICATION_NAME ${PROJECT_NAME}) @@ -25,7 +25,7 @@ # Increment PATCH. set(LIBRARY_VERSION_MAJOR 0) set(LIBRARY_VERSION_MINOR 3) -set(LIBRARY_VERSION_PATCH 3) +set(LIBRARY_VERSION_PATCH 4) set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) @@ -84,6 +84,9 @@ ) # cmake config files +set(PACKAGE_NAME nss_wrapper) +set(PACKAGE_NAME_UPPER NSS_WRAPPER) + configure_file(nss_wrapper-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config-version.cmake @ONLY) configure_file(nss_wrapper-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config.cmake @ONLY) install( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/nss_wrapper-config-version.cmake.in new/nss_wrapper-1.1.15/nss_wrapper-config-version.cmake.in --- old/nss_wrapper-1.1.13/nss_wrapper-config-version.cmake.in 2020-03-17 18:23:32.000000000 +0100 +++ new/nss_wrapper-1.1.15/nss_wrapper-config-version.cmake.in 2023-01-25 12:09:01.000000000 +0100 @@ -1,11 +1,40 @@ set(PACKAGE_VERSION @PROJECT_VERSION@) -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) + if(${PACKAGE_VERSION} MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") endif() + else() + set(CVF_VERSION_MAJOR ${PACKAGE_VERSION}) + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/nss_wrapper-config.cmake.in new/nss_wrapper-1.1.15/nss_wrapper-config.cmake.in --- old/nss_wrapper-1.1.13/nss_wrapper-config.cmake.in 2020-03-17 18:23:32.000000000 +0100 +++ new/nss_wrapper-1.1.15/nss_wrapper-config.cmake.in 2023-01-25 12:09:01.000000000 +0100 @@ -1 +1,14 @@ -set(NSS_WRAPPER_LIBRARY @CMAKE_INSTALL_FULL_LIBDIR@/@NSS_WRAPPER_LIB@) +set(@PACKAGE_NAME_UPPER@_LIBRARY @CMAKE_INSTALL_FULL_LIBDIR@/@NSS_WRAPPER_LIB@) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_NAME@-config-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_files) +unset(_cmake_config_file) + +include(FindPackageMessage) +find_package_message(@PACKAGE_NAME@ + "Found @PACKAGE_NAME@: ${@PACKAGE_NAME_UPPER@_LIBRARY} (version \"${PACKAGE_VERSION}\")" + "[${@PACKAGE_NAME_UPPER@_LIBRARY}][${PACKAGE_VERSION}]") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/src/CMakeLists.txt new/nss_wrapper-1.1.15/src/CMakeLists.txt --- old/nss_wrapper-1.1.13/src/CMakeLists.txt 2020-03-17 18:23:32.000000000 +0100 +++ new/nss_wrapper-1.1.15/src/CMakeLists.txt 2023-01-25 13:25:00.000000000 +0100 @@ -1,5 +1,10 @@ project(libnss_wrapper C) +add_library(nss_utils STATIC nss_utils.c) +target_compile_options(nss_utils + PRIVATE + ${DEFAULT_C_COMPILE_FLAGS}) + add_library(nss_wrapper SHARED nss_wrapper.c) target_compile_options(nss_wrapper PRIVATE @@ -12,7 +17,7 @@ target_include_directories(nss_wrapper PRIVATE ${CMAKE_BINARY_DIR}) -target_link_libraries(nss_wrapper ${NWRAP_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(nss_wrapper nss_utils ${NWRAP_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( nss_wrapper diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/src/nss_utils.c new/nss_wrapper-1.1.15/src/nss_utils.c --- old/nss_wrapper-1.1.13/src/nss_utils.c 1970-01-01 01:00:00.000000000 +0100 +++ new/nss_wrapper-1.1.15/src/nss_utils.c 2023-01-25 12:09:01.000000000 +0100 @@ -0,0 +1,131 @@ +/* + * BSD 3-Clause License + * + * Copyright (c) 2007, Stefan Metzmacher <[email protected]> + * Copyright (c) 2009, Guenther Deschner <[email protected]> + * Copyright (c) 2014-2015, Michael Adam <[email protected]> + * Copyright (c) 2015, Robin Hack <[email protected]> + * Copyright (c) 2013-2018, Andreas Schneider <[email protected]> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <grp.h> +#include <string.h> +#include <stdint.h> + +#include "nss_utils.h" + +int nwrap_gr_copy_r(const struct group *src, struct group *dst, + char *buf, size_t buflen, struct group **dstp) +{ + char *p = NULL; + uintptr_t align = 0; + unsigned int gr_mem_cnt = 0; + unsigned i; + size_t total_len; + size_t gr_name_len = strlen(src->gr_name) + 1; + size_t gr_passwd_len = strlen(src->gr_passwd) + 1; + union { + char *ptr; + char **data; + } g_mem; + + for (i = 0; src->gr_mem[i] != NULL; i++) { + gr_mem_cnt++; + } + + /* Align the memory for storing pointers */ + align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *)); + total_len = align + + (1 + gr_mem_cnt) * sizeof(char *) + + gr_name_len + gr_passwd_len; + + if (total_len > buflen) { + errno = ERANGE; + return -1; + } + buflen -= total_len; + + /* gr_mem */ + p = buf + align; + g_mem.ptr = p; + dst->gr_mem = g_mem.data; + + /* gr_name */ + p += (1 + gr_mem_cnt) * sizeof(char *); + dst->gr_name = p; + + /* gr_passwd */ + p += gr_name_len; + dst->gr_passwd = p; + + /* gr_mem[x] */ + p += gr_passwd_len; + + /* gr_gid */ + dst->gr_gid = src->gr_gid; + + memcpy(dst->gr_name, src->gr_name, gr_name_len); + + memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len); + + /* Set the terminating entry */ + dst->gr_mem[gr_mem_cnt] = NULL; + + /* Now add the group members content */ + total_len = 0; + for (i = 0; i < gr_mem_cnt; i++) { + size_t len = strlen(src->gr_mem[i]) + 1; + + dst->gr_mem[i] = p; + total_len += len; + p += len; + } + + if (total_len > buflen) { + errno = ERANGE; + return -1; + } + + for (i = 0; i < gr_mem_cnt; i++) { + size_t len = strlen(src->gr_mem[i]) + 1; + + memcpy(dst->gr_mem[i], + src->gr_mem[i], + len); + } + + if (dstp != NULL) { + *dstp = dst; + } + + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/src/nss_utils.h new/nss_wrapper-1.1.15/src/nss_utils.h --- old/nss_wrapper-1.1.13/src/nss_utils.h 1970-01-01 01:00:00.000000000 +0100 +++ new/nss_wrapper-1.1.15/src/nss_utils.h 2023-01-25 12:09:01.000000000 +0100 @@ -0,0 +1,46 @@ +/* + * BSD 3-Clause License + * + * Copyright (c) 2007, Stefan Metzmacher <[email protected]> + * Copyright (c) 2009, Guenther Deschner <[email protected]> + * Copyright (c) 2014-2015, Michael Adam <[email protected]> + * Copyright (c) 2015, Robin Hack <[email protected]> + * Copyright (c) 2013-2018, Andreas Schneider <[email protected]> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NSS_UTILS_H +#define NSS_UTILS_H +#include <grp.h> + +int nwrap_gr_copy_r(const struct group *src, struct group *dst, + char *buf, size_t buflen, struct group **dstp); + +#endif //NSS_UTILS_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/src/nss_wrapper.c new/nss_wrapper-1.1.15/src/nss_wrapper.c --- old/nss_wrapper-1.1.13/src/nss_wrapper.c 2022-11-09 07:45:15.000000000 +0100 +++ new/nss_wrapper-1.1.15/src/nss_wrapper.c 2023-01-25 12:09:01.000000000 +0100 @@ -54,12 +54,14 @@ #include <string.h> #include <unistd.h> #include <ctype.h> +#include <limits.h> #include <netinet/in.h> #include <search.h> #include <assert.h> +#include "nss_utils.h" /* * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on @@ -177,6 +179,9 @@ #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN #endif +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#define MIN(a,b) ((a) > (b) ? (b) : (a)) + static bool nwrap_initialized = false; static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -516,7 +521,7 @@ size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_endpwent)(void); -typedef NSS_STATUS (*__nss_initgroups)(const char *user, +typedef NSS_STATUS (*__nss_initgroups_dyn)(const char *user, gid_t group, long int *start, long int *size, @@ -568,7 +573,7 @@ NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwent_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(endpwent); - NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups); + NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups_dyn); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrnam_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrgid_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(setgrent); @@ -606,8 +611,14 @@ struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); void (*nw_endpwent)(struct nwrap_backend *b); - int (*nw_initgroups)(struct nwrap_backend *b, - const char *user, gid_t group); + int (*nw_initgroups_dyn)(struct nwrap_backend *b, + const char *user, + gid_t group, + long int *start, + long int *size, + gid_t **groups, + long int limit, + int *errnop); struct group * (*nw_getgrnam)(struct nwrap_backend *b, const char *name); int (*nw_getgrnam_r)(struct nwrap_backend *b, @@ -663,8 +674,14 @@ struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_files_endpwent(struct nwrap_backend *b); -static int nwrap_files_initgroups(struct nwrap_backend *b, - const char *user, gid_t group); +static int nwrap_files_initgroups_dyn(struct nwrap_backend *b, + const char *user, + gid_t group, + long int *start, + long int *size, + gid_t **groups, + long int limit, + int *errnop); static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, const char *name); static int nwrap_files_getgrnam_r(struct nwrap_backend *b, @@ -730,8 +747,14 @@ char *buf, size_t buflen, struct group **grdstp); static void nwrap_module_setgrent(struct nwrap_backend *b); static void nwrap_module_endgrent(struct nwrap_backend *b); -static int nwrap_module_initgroups(struct nwrap_backend *b, - const char *user, gid_t group); +static int nwrap_module_initgroups_dyn(struct nwrap_backend *b, + const char *user, + gid_t group, + long int *start, + long int *size, + gid_t **groups, + long int limit, + int *errnop); static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b, const void *addr, socklen_t len, int type); @@ -754,7 +777,7 @@ .nw_getpwent = nwrap_files_getpwent, .nw_getpwent_r = nwrap_files_getpwent_r, .nw_endpwent = nwrap_files_endpwent, - .nw_initgroups = nwrap_files_initgroups, + .nw_initgroups_dyn = nwrap_files_initgroups_dyn, .nw_getgrnam = nwrap_files_getgrnam, .nw_getgrnam_r = nwrap_files_getgrnam_r, .nw_getgrgid = nwrap_files_getgrgid, @@ -780,7 +803,7 @@ .nw_getpwent = nwrap_module_getpwent, .nw_getpwent_r = nwrap_module_getpwent_r, .nw_endpwent = nwrap_module_endpwent, - .nw_initgroups = nwrap_module_initgroups, + .nw_initgroups_dyn = nwrap_module_initgroups_dyn, .nw_getgrnam = nwrap_module_getgrnam, .nw_getgrnam_r = nwrap_module_getgrnam_r, .nw_getgrgid = nwrap_module_getgrgid, @@ -820,6 +843,14 @@ struct addrinfo **pai, bool skip_canonname); +#ifdef HAVE_GETGROUPLIST +static int nwrap_getgrouplist(const char *user, + gid_t group, + long int *size, + gid_t **groupsp, + long int limit); +#endif + /* * VECTORS */ @@ -1826,7 +1857,7 @@ nwrap_nss_module_bind_symbol(setpwent); nwrap_nss_module_bind_symbol(getpwent_r); nwrap_nss_module_bind_symbol(endpwent); - nwrap_nss_module_bind_symbol2(initgroups, initgroups_dyn); + nwrap_nss_module_bind_symbol(initgroups_dyn); nwrap_nss_module_bind_symbol(getgrnam_r); nwrap_nss_module_bind_symbol(getgrgid_r); nwrap_nss_module_bind_symbol(setgrent); @@ -2983,93 +3014,6 @@ nwrap_gr->idx = 0; } -static int nwrap_gr_copy_r(const struct group *src, struct group *dst, - char *buf, size_t buflen, struct group **dstp) -{ - char *p = NULL; - uintptr_t align = 0; - unsigned int gr_mem_cnt = 0; - unsigned i; - size_t total_len; - size_t gr_name_len = strlen(src->gr_name) + 1; - size_t gr_passwd_len = strlen(src->gr_passwd) + 1; - union { - char *ptr; - char **data; - } g_mem; - - for (i = 0; src->gr_mem[i] != NULL; i++) { - gr_mem_cnt++; - } - - /* Align the memory for storing pointers */ - align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *)); - total_len = align + - (1 + gr_mem_cnt) * sizeof(char *) + - gr_name_len + gr_passwd_len; - - if (total_len > buflen) { - errno = ERANGE; - return -1; - } - buflen -= total_len; - - /* gr_mem */ - p = buf + align; - g_mem.ptr = p; - dst->gr_mem = g_mem.data; - - /* gr_name */ - p += (1 + gr_mem_cnt) * sizeof(char *); - dst->gr_name = p; - - /* gr_passwd */ - p += gr_name_len; - dst->gr_passwd = p; - - /* gr_mem[x] */ - p += gr_passwd_len; - - /* gr_gid */ - dst->gr_gid = src->gr_gid; - - memcpy(dst->gr_name, src->gr_name, gr_name_len); - - memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len); - - /* Set the terminating entry */ - dst->gr_mem[gr_mem_cnt] = NULL; - - /* Now add the group members content */ - total_len = 0; - for (i = 0; i < gr_mem_cnt; i++) { - size_t len = strlen(src->gr_mem[i]) + 1; - - dst->gr_mem[i] = p; - total_len += len; - p += len; - } - - if (total_len > buflen) { - errno = ERANGE; - return -1; - } - - for (i = 0; i < gr_mem_cnt; i++) { - size_t len = strlen(src->gr_mem[i]) + 1; - - memcpy(dst->gr_mem[i], - src->gr_mem[i], - len); - } - - if (dstp != NULL) { - *dstp = dst; - } - - return 0; -} - static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed) { struct nwrap_entlist *el; @@ -3691,27 +3635,21 @@ #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* misc functions */ -static int nwrap_files_initgroups(struct nwrap_backend *b, - const char *user, - gid_t group) +static int nwrap_files_initgroups_dyn(struct nwrap_backend *b, + const char *user, + gid_t group, + long int *start, + long int *size, + gid_t **groups, + long int limit, + int *errnop) { struct group *grp; - gid_t *groups; - int size = 1; - int rc; - - groups = (gid_t *)malloc(size * sizeof(gid_t)); - if (groups == NULL) { - NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); - errno = ENOMEM; - return -1; - } - groups[0] = group; + int i = 0; + (void)errnop; /* unused */ nwrap_files_setgrent(b); while ((grp = nwrap_files_getgrent(b)) != NULL) { - int i = 0; - NWRAP_LOG(NWRAP_LOG_DEBUG, "Inspecting %s for group membership", grp->gr_name); @@ -3724,33 +3662,31 @@ user, grp->gr_name); - groups = (gid_t *)realloc(groups, - (size + 1) * sizeof(gid_t)); - if (groups == NULL) { - NWRAP_LOG(NWRAP_LOG_ERROR, - "Out of memory"); - errno = ENOMEM; - return -1; + if (*start == *size) { + long int newsize; + gid_t *newgroups; + + newsize = 2 * (*size); + if (limit > 0 && newsize > limit) { + newsize = MAX(limit, *size); + } + newgroups = (gid_t *) realloc((*groups), + newsize * sizeof(**groups)); + if (!newgroups) { + errno = ENOMEM; + return -1; + } + *groups = newgroups; + *size = newsize; } - - groups[size] = grp->gr_gid; - size++; + (*groups)[*start] = grp->gr_gid; + (*start)++; } } } nwrap_files_endgrent(b); - - NWRAP_LOG(NWRAP_LOG_DEBUG, - "%s is member of %d groups", - user, size); - - /* This really only works if uid_wrapper is loaded */ - rc = setgroups(size, groups); - - free(groups); - - return rc; + return *start; } /* group functions */ @@ -4587,24 +4523,26 @@ b->symbols->_nss_endpwent.f(); } -static int nwrap_module_initgroups(struct nwrap_backend *b, - const char *user, gid_t group) +static int nwrap_module_initgroups_dyn(struct nwrap_backend *b, + const char *user, + gid_t group, + long int *start, + long int *size, + gid_t **groups, + long int limit, + int *errnop) { - gid_t *groups; - long int start; - long int size; - - if (b->symbols->_nss_initgroups.f == NULL) { + if (b->symbols->_nss_initgroups_dyn.f == NULL) { return NSS_STATUS_UNAVAIL; } - return b->symbols->_nss_initgroups.f(user, + return b->symbols->_nss_initgroups_dyn.f(user, group, - &start, - &size, - &groups, - 0, - &errno); + start, + size, + groups, + limit, + errnop); } static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, @@ -5305,20 +5243,49 @@ static int nwrap_initgroups(const char *user, gid_t group) { - size_t i; +#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 + /* No extra groups allowed. */ + return 0; +#elif !defined(HAVE_GETGROUPLIST) + return 0; +#else + long int size; + long int limit; + gid_t *groups; + int ngroups; + int result; + const char *env = getenv("UID_WRAPPER"); - for (i=0; i < nwrap_main_global->num_backends; i++) { - struct nwrap_backend *b = &nwrap_main_global->backends[i]; - int rc; + if (env == NULL || env[0] != '1') { + NWRAP_LOG(NWRAP_LOG_WARN, + "initgroups() requires uid_wrapper to work!"); + return 0; + } - rc = b->ops->nw_initgroups(b, user, group); - if (rc == 0) { - return 0; - } + limit = sysconf(_SC_NGROUPS_MAX); + if (limit > 0) { + size = MIN(limit, 64); + } else { + size = 16; } - errno = ENOENT; - return -1; + groups = (gid_t *)malloc(size * sizeof(gid_t)); + if (groups == NULL) { + /* No more memory. */ + return -1; + } + + ngroups = nwrap_getgrouplist(user, group, &size, &groups, limit); + + /* Try to set the maximum number of groups the kernel can handle. */ + do { + result = setgroups(ngroups, groups); + } while (result == -1 && errno == EINVAL && --ngroups > 0); + + free(groups); + + return result; +#endif } int initgroups(const char *user, gid_t group) @@ -5616,81 +5583,85 @@ ***************************************************************************/ #ifdef HAVE_GETGROUPLIST -static int nwrap_getgrouplist(const char *user, gid_t group, - gid_t *groups, int *ngroups) -{ - struct group *grp; - gid_t *groups_tmp; - int count = 1; - - NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user); - - groups_tmp = (gid_t *)malloc(count * sizeof(gid_t)); - if (!groups_tmp) { - NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); - errno = ENOMEM; - return -1; - } - groups_tmp[0] = group; - - nwrap_setgrent(); - while ((grp = nwrap_getgrent()) != NULL) { - int i = 0; - - NWRAP_LOG(NWRAP_LOG_DEBUG, - "Inspecting %s for group membership", - grp->gr_name); - - for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { +static int nwrap_getgrouplist(const char *user, + gid_t group, + long int *size, + gid_t **groupsp, + long int limit) +{ + enum nss_status status = NSS_STATUS_UNAVAIL; + /* Start is one, because we have the first group as parameter. */ + long int start = 1; + size_t i; - if (group != grp->gr_gid && - (strcmp(user, grp->gr_mem[i]) == 0)) { + /* Never store more than the starting *SIZE number of elements. */ + assert(*size > 0); + (*groupsp)[0] = group; - NWRAP_LOG(NWRAP_LOG_DEBUG, - "%s is member of %s", - user, - grp->gr_name); + for (i = 0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + long int prev_start = start; + long int cnt = prev_start; - groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t)); - if (!groups_tmp) { - NWRAP_LOG(NWRAP_LOG_ERROR, - "Out of memory"); - errno = ENOMEM; - return -1; - } - groups_tmp[count] = grp->gr_gid; + status = b->ops->nw_initgroups_dyn(b, + user, + group, + &start, + size, + groupsp, + limit, + &errno); + + /* Remove duplicates. */ + while (cnt < start) { + long int inner; + for (inner = 0; inner < prev_start; ++inner) + if ((*groupsp)[inner] == (*groupsp)[cnt]) + break; - count++; - } + if (inner < prev_start) + (*groupsp)[cnt] = (*groupsp)[--start]; + else + ++cnt; } + NWRAP_LOG(NWRAP_LOG_DEBUG, + "Resource '%s' returned status=%d and increased " + "count of groups to %ld", + b->name, + status, + start); } + return start; +} - nwrap_endgrent(); +int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + long int size; + int total, retval; + gid_t *newgroups; - NWRAP_LOG(NWRAP_LOG_DEBUG, - "%s is member of %d groups", - user, *ngroups); + if (!nss_wrapper_enabled()) { + return libc_getgrouplist(user, group, groups, ngroups); + } - if (*ngroups < count) { - *ngroups = count; - free(groups_tmp); + size = MAX(1, *ngroups); + newgroups = (gid_t *)malloc(size * sizeof(gid_t)); + if (newgroups == NULL) { return -1; } - *ngroups = count; - memcpy(groups, groups_tmp, count * sizeof(gid_t)); - free(groups_tmp); + total = nwrap_getgrouplist(user, group, &size, &newgroups, -1); - return count; -} - -int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) -{ - if (!nss_wrapper_enabled()) { - return libc_getgrouplist(user, group, groups, ngroups); + if (groups != NULL) { + memcpy(groups, newgroups, MIN(*ngroups, total) * sizeof(gid_t)); } - return nwrap_getgrouplist(user, group, groups, ngroups); + free(newgroups); + + retval = total > *ngroups ? -1 : total; + *ngroups = total; + + return retval; } #endif @@ -6499,13 +6470,25 @@ /* libc */ if (m->libc != NULL) { - if (m->libc->handle != NULL) { + if (m->libc->handle != NULL +#ifdef RTLD_NEXT + && m->libc->handle != RTLD_NEXT +#endif + ) { dlclose(m->libc->handle); } - if (m->libc->nsl_handle != NULL) { + if (m->libc->nsl_handle != NULL +#ifdef RTLD_NEXT + && m->libc->nsl_handle != RTLD_NEXT +#endif + ) { dlclose(m->libc->nsl_handle); } - if (m->libc->sock_handle != NULL) { + if (m->libc->sock_handle != NULL +#ifdef RTLD_NEXT + && m->libc->sock_handle != RTLD_NEXT +#endif + ) { dlclose(m->libc->sock_handle); } SAFE_FREE(m->libc); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/tests/CMakeLists.txt new/nss_wrapper-1.1.15/tests/CMakeLists.txt --- old/nss_wrapper-1.1.13/tests/CMakeLists.txt 2022-11-09 07:45:15.000000000 +0100 +++ new/nss_wrapper-1.1.15/tests/CMakeLists.txt 2023-01-25 13:25:00.000000000 +0100 @@ -1,6 +1,6 @@ project(tests C) -set(TESTSUITE_LIBRARIES ${NWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY}) +set(TESTSUITE_LIBRARIES nss_utils ${NWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY}) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) add_library(nss_nwrap SHARED nss_nwrap.c) @@ -11,6 +11,7 @@ PRIVATE ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR}) +target_link_libraries(nss_nwrap PRIVATE nss_utils) set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -19,6 +20,10 @@ configure_file(hosts.in ${CMAKE_CURRENT_BINARY_DIR}/hosts @ONLY) configure_file(shadow.in ${CMAKE_CURRENT_BINARY_DIR}/shadow @ONLY) +# If there is uid_wrapper, we can better test initgroups() since uid_wrapper +# provides privilege for setgroups(). +find_package(uid_wrapper 1.3.0) + set(NWRAP_TESTS testsuite test_nwrap_vector @@ -26,7 +31,8 @@ test_getnameinfo test_gethostby_name_addr test_gethostent - test_getpwuid_module) + test_getpwuid_module + test_initgroups) if (HAVE_SHADOW_H) list(APPEND NWRAP_TESTS test_shadow) @@ -51,6 +57,9 @@ if (ASAN_LIBRARY) list(APPEND PRELOAD_LIBRARIES ${ASAN_LIBRARY}) endif() + if (uid_wrapper_FOUND) + list(APPEND PRELOAD_LIBRARIES ${UID_WRAPPER_LIBRARY}) + endif() list(APPEND PRELOAD_LIBRARIES ${NSS_WRAPPER_LOCATION}) if (OSX) @@ -60,6 +69,10 @@ set(TORTURE_ENVIRONMENT "LD_PRELOAD=${_TMP_ENV}") endif() + if (uid_wrapper_FOUND) + list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER=1) + endif() + list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_PASSWD=${CMAKE_CURRENT_BINARY_DIR}/passwd) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_GROUP=${CMAKE_CURRENT_BINARY_DIR}/group) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_SHADOW=${CMAKE_CURRENT_BINARY_DIR}/shadow) @@ -71,6 +84,9 @@ if (CMAKE_BUILD_TYPE_LOWER STREQUAL "threadsanitizer") list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_DISABLE_DEEPBIND=1) + if (uid_wrapper_FOUND) + list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER_DISABLE_DEEPBIND=1) + endif() endif() endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/tests/group.in new/nss_wrapper-1.1.15/tests/group.in --- old/nss_wrapper-1.1.13/tests/group.in 2019-02-15 16:39:32.000000000 +0100 +++ new/nss_wrapper-1.1.15/tests/group.in 2023-01-25 12:09:01.000000000 +0100 @@ -1,4 +1,5 @@ -users:x:1000: +users:x:1000:alice,bob +all:x:1002:alice,bob,nobody,root nobody:x:65533: nogroup:x:65534:nobody root:x:65532: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/tests/nss_nwrap.c new/nss_wrapper-1.1.15/tests/nss_nwrap.c --- old/nss_wrapper-1.1.13/tests/nss_nwrap.c 2020-04-02 13:37:22.000000000 +0200 +++ new/nss_wrapper-1.1.15/tests/nss_nwrap.c 2023-01-25 12:09:01.000000000 +0100 @@ -7,6 +7,9 @@ #include <string.h> #include <pwd.h> #include <grp.h> +#include <stdlib.h> + +#include "../src/nss_utils.h" #if defined(HAVE_NSS_H) /* Linux and BSD */ @@ -29,6 +32,14 @@ # error "No nsswitch support detected" #endif +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + NSS_STATUS _nss_nwrap_setpwent(void); NSS_STATUS _nss_nwrap_endpwent(void); NSS_STATUS _nss_nwrap_getpwent_r(struct passwd *result, char *buffer, @@ -39,12 +50,20 @@ char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_setgrent(void); NSS_STATUS _nss_nwrap_endgrent(void); -NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, struct group *result, char *buffer, - size_t buflen, int *errnop); +NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp); +NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, + struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp); +NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, + struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp); NSS_STATUS _nss_nwrap_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); @@ -133,6 +152,7 @@ NSS_STATUS _nss_nwrap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { + (void)errnop; /* unused */ if (uid == 424242) { char buf[] = "hanswurst\0secret\0\0/home/hanswurst\0/bin/false"; const struct passwd src = { @@ -165,50 +185,116 @@ return NSS_STATUS_UNAVAIL; } +static int grent_idx = 0; NSS_STATUS _nss_nwrap_setgrent(void) { - return NSS_STATUS_UNAVAIL; + grent_idx = 0; + return NSS_STATUS_SUCCESS; } NSS_STATUS _nss_nwrap_endgrent(void) { - return NSS_STATUS_UNAVAIL; + grent_idx = 0; + return NSS_STATUS_SUCCESS; } -NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - (void) result; - (void) buffer; - (void) buflen; - (void) errnop; - - return NSS_STATUS_UNAVAIL; +static const struct group gr0 = { + .gr_name = discard_const_p(char, "wb_group_0"), + .gr_passwd = discard_const_p(char, "x"), + .gr_gid = 100010, + .gr_mem = (char *[]) { + discard_const_p(char, "alice"), + discard_const_p(char, "bob"), + NULL + }, +}; +static const struct group gr1 = { + .gr_name = discard_const_p(char, "wb_group_1"), + .gr_passwd = discard_const_p(char, "x"), + .gr_gid = 100011, + .gr_mem = (char *[]) { + discard_const_p(char, "alice"), + discard_const_p(char, "bob"), + NULL + }, +}; +static const struct group gr2 = { + .gr_name = discard_const_p(char, "wb_group_2"), + .gr_passwd = discard_const_p(char, "x"), + .gr_gid = 100012, + .gr_mem = (char *[]) { + discard_const_p(char, "alice"), + NULL + }, +}; + +NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp) +{ + switch (grent_idx) { + int ret; + case 0: + ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); + grent_idx++; + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + case 1: + ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); + grent_idx++; + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + case 2: + ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); + grent_idx++; + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + default: + return NSS_STATUS_NOTFOUND; + } } -NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - (void) name; - (void) result; - (void) buffer; - (void) buflen; - (void) errnop; - - return NSS_STATUS_UNAVAIL; +NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, + struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp) +{ + int ret; + + if (strcmp(name, "wb_group_0") == 0) { + ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + } else if (strcmp(name, "wb_group_1") == 0) { + ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + } else if (strcmp(name, "wb_group_2") == 0) { + ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + } else { + return NSS_STATUS_NOTFOUND; + } } -NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - (void) gid; - (void) result; - (void) buffer; - (void) buflen; - (void) errnop; - - return NSS_STATUS_UNAVAIL; +NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, + struct group *result, + char *buffer, + size_t buflen, + struct group **grdstp) +{ + int ret; + switch (gid) { + case 100010: + ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + case 100011: + ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + case 100012: + ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); + return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; + default: + return NSS_STATUS_NOTFOUND; + } } NSS_STATUS _nss_nwrap_initgroups_dyn(char *user, gid_t group, long int *start, @@ -216,13 +302,40 @@ long int limit, int *errnop) { (void) user; - (void) group; - (void) start; - (void) size; - (void) groups; + (void)group; (void) limit; (void) errnop; - return NSS_STATUS_UNAVAIL; + if (!(strcmp(user, "alice") == 0 || strcmp(user, "bob") == 0)) { + return NSS_STATUS_SUCCESS; + } + + if (*start + 4 >= *size) { + long int newsize; + gid_t *newgroups; + + newsize = *size + 4; + if (limit > 0) { + if (newsize > limit) { + return NSS_STATUS_NOTFOUND; + } + } + + newgroups = + (gid_t *)realloc((*groups), newsize * sizeof(**groups)); + if (!newgroups) { + *errnop = ENOMEM; + return NSS_STATUS_NOTFOUND; + } + *groups = newgroups; + *size = newsize; + } + + (*groups)[(*start)++] = 100010; + (*groups)[(*start)++] = 100011; + if (strcmp(user, "alice") == 0) { + (*groups)[(*start)++] = 100012; + } + return NSS_STATUS_SUCCESS; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nss_wrapper-1.1.13/tests/test_initgroups.c new/nss_wrapper-1.1.15/tests/test_initgroups.c --- old/nss_wrapper-1.1.13/tests/test_initgroups.c 1970-01-01 01:00:00.000000000 +0100 +++ new/nss_wrapper-1.1.15/tests/test_initgroups.c 2023-01-25 16:41:14.000000000 +0100 @@ -0,0 +1,53 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <unistd.h> +#include <stdlib.h> +#include <grp.h> +#include <errno.h> + +static void test_nwrap_initgroups(void **state) +{ + gid_t gid = 10000; + int ret, i; + int ngroups; + const char *env = getenv("UID_WRAPPER"); + + (void)state; /* unused */ + + /* initgroups() sets {10000, 1000, 1002, 100010, 100011, 100012} */ + ret = initgroups("alice", gid); + assert_return_code(ret, errno); + + /* + * nss_wrapper() in nwrap_initgroups() makes early return if UID_WRAPPER + * is not present. The reason is that we need privilege for setgroups() + * called from initgroups() and we get it only with UID_WRAPPER + */ + if (env != NULL && env[0] == '1') { + gid_t groups1[6] = {10000, 1000, 1002, 100010, 100011, 100012}; + gid_t *groups2 = malloc(10 * sizeof(gid_t)); + + assert_non_null(groups2); + ngroups = getgroups(10, groups2); /* room for 10, expect 6 */ + assert_int_equal(ngroups, 6); + for (i = 0; i < 6; i++) { + assert_int_equal(groups1[i], groups2[i]); + } + free(groups2); + } +} + +int main(void) +{ + int rc; + + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_nwrap_initgroups) + }; + + rc = cmocka_run_group_tests(tests, NULL, NULL); + + return rc; +}
