nss_wrapper-1.1.3/COPYING000644 001750 000144 00000003076 12247646107 015111 0ustar00asnusers000000 000000 Copyright (C) Stefan Metzmacher 2007 Copyright (C) Guenther Deschner 2009 Copyright (C) Andreas Schneider 2013 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. nss_wrapper-1.1.3/DefineOptions.cmake000644 001750 000144 00000000061 12247646107 017615 0ustar00asnusers000000 000000 option(UNIT_TESTING "Build with unit tests" OFF) nss_wrapper-1.1.3/cmake/000755 001750 000144 00000000000 12672772135 015133 5ustar00asnusers000000 000000 nss_wrapper-1.1.3/cmake/Modules/000755 001750 000144 00000000000 12672772135 016543 5ustar00asnusers000000 000000 nss_wrapper-1.1.3/cmake/Modules/AddCMockaTest.cmake000644 001750 000144 00000002373 12247646107 022155 0ustar00asnusers000000 000000 # - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN) # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2010 Andreas Schneider # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. enable_testing() include(CTest) if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags") set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) function (ADD_CMOCKA_TEST _testName _testSource) add_executable(${_testName} ${_testSource}) target_link_libraries(${_testName} ${ARGN}) add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}) endfunction (ADD_CMOCKA_TEST) nss_wrapper-1.1.3/cmake/Modules/COPYING-CMAKE-SCRIPTS000644 001750 000144 00000002457 12247646107 021546 0ustar00asnusers000000 000000 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 copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. nss_wrapper-1.1.3/cmake/Modules/CheckCCompilerFlagSSP.cmake000644 001750 000144 00000001755 12247646107 023545 0ustar00asnusers000000 000000 # - Check whether the C compiler supports a given flag in the # context of a stack checking compiler option. # CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE) # # FLAG - the compiler flag # VARIABLE - variable to store the result # # This actually calls check_c_source_compiles. # See help for CheckCSourceCompiles for a listing of variables # that can modify the build. # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(CheckCSourceCompiles) function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT}) set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") endfunction(CHECK_C_COMPILER_FLAG_SSP) nss_wrapper-1.1.3/cmake/Modules/DefineInstallationPaths.cmake000644 001750 000144 00000007343 12267205751 024323 0ustar00asnusers000000 000000 if (UNIX OR OS2) IF (NOT APPLICATION_NAME) MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") SET(APPLICATION_NAME ${PROJECT_NAME}) ENDIF (NOT APPLICATION_NAME) # Suffix for Linux SET(LIB_SUFFIX CACHE STRING "Define suffix of directory name (32/64)" ) SET(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries" ) SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Base directory for files which go to share/" ) SET(DATA_INSTALL_PREFIX "${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}" CACHE PATH "The parent directory where applications can install their data") # The following are directories where stuff will be installed to SET(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)" ) SET(SBIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/sbin" CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)" ) SET(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" ) SET(LIBEXEC_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/libexec" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" ) SET(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/${APPLICATION_NAME}" CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})" ) SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix (default prefix/include)" ) set(CMAKE_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake" CACHE PATH "The subdirectory to install cmake config files") SET(DATA_INSTALL_DIR "${DATA_INSTALL_PREFIX}" CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})" ) SET(HTML_INSTALL_DIR "${DATA_INSTALL_PREFIX}/doc/HTML" CACHE PATH "The HTML install dir for documentation (default data/doc/html)" ) SET(ICON_INSTALL_DIR "${DATA_INSTALL_PREFIX}/icons" CACHE PATH "The icon install dir (default data/icons/)" ) SET(SOUND_INSTALL_DIR "${DATA_INSTALL_PREFIX}/sounds" CACHE PATH "The install dir for sound files (default data/sounds)" ) SET(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale" CACHE PATH "The install dir for translations (default prefix/share/locale)" ) SET(XDG_APPS_DIR "${SHARE_INSTALL_PREFIX}/applications/" CACHE PATH "The XDG apps dir" ) SET(XDG_DIRECTORY_DIR "${SHARE_INSTALL_PREFIX}/desktop-directories" CACHE PATH "The XDG directory" ) SET(SYSCONF_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/etc" CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" ) SET(MAN_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/man" CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)" ) SET(INFO_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/info" CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)" ) else() # Same same set(BIN_INSTALL_DIR "bin" CACHE PATH "-") set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-") set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-") set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-") set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-") set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-") set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-") set(ICON_INSTALL_DIR "icons" CACHE PATH "-") set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-") set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-") endif () nss_wrapper-1.1.3/cmake/Modules/DefinePlatformDefaults.cmake000644 001750 000144 00000001312 12247646107 024126 0ustar00asnusers000000 000000 # Set system vars if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(LINUX TRUE) endif(CMAKE_SYSTEM_NAME MATCHES "Linux") if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(FREEBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") set(OPENBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") set(NETBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") set(SOLARIS TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") if (CMAKE_SYSTEM_NAME MATCHES "OS2") set(OS2 TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OS2") nss_wrapper-1.1.3/cmake/Modules/FindCMocka.cmake000644 001750 000144 00000002726 12247646107 021507 0ustar00asnusers000000 000000 # - Try to find CMocka # Once done this will define # # CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka # # Read-Only variables: # CMOCKA_FOUND - system has CMocka # CMOCKA_INCLUDE_DIR - the CMocka include directory # CMOCKA_LIBRARIES - Link these to use CMocka # CMOCKA_DEFINITIONS - Compiler switches required for using CMocka # #============================================================================= # Copyright (c) 2011-2012 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # find_path(CMOCKA_INCLUDE_DIR NAMES cmocka.h PATHS ${CMOCKA_ROOT_DIR}/include ) find_library(CMOCKA_LIBRARY NAMES cmocka PATHS ${CMOCKA_ROOT_DIR}/include ) if (CMOCKA_LIBRARY) set(CMOCKA_LIBRARIES ${CMOCKA_LIBRARIES} ${CMOCKA_LIBRARY} ) endif (CMOCKA_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR) # show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES) nss_wrapper-1.1.3/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake000644 001750 000144 00000001227 12247646107 025105 0ustar00asnusers000000 000000 # - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) if (_insource) message(SEND_ERROR "${_errorMessage}") message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") endif (_insource) endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) nss_wrapper-1.1.3/cmake/Modules/DefineCMakeDefaults.cmake000644 001750 000144 00000001741 12320724461 023320 0ustar00asnusers000000 000000 # Always include srcdir and builddir in include path # This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in # about every subdir # since cmake 2.4.0 set(CMAKE_INCLUDE_CURRENT_DIR ON) # Put the include dirs which are in the source or build tree # before all other include dirs, so the headers in the sources # are prefered over the already installed ones # since cmake 2.4.1 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # Use colored output # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here set(GENERIC_LIB_VERSION "0.1.0") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." ) endif (NOT CMAKE_BUILD_TYPE) # Create the compile command database for clang by default set(CMAKE_EXPORT_COMPILE_COMMANDS ON) nss_wrapper-1.1.3/cmake/Modules/DefineCompilerFlags.cmake000644 001750 000144 00000006506 12620616655 023413 0ustar00asnusers000000 000000 # define system dependent compiler flags include(CheckCCompilerFlag) include(CheckCCompilerFlagSSP) if (UNIX AND NOT WIN32) # # Define GNUCC compiler flags # if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") # add -Wconversion ? set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -fstrict-aliasing -Wbad-function-cast") # check -Wstrict-aliasing support check_c_compiler_flag("-Wstrict-aliasing=3" WITH_WSTRICT_ALIASING) if (WITH_WSTRICT_ALIASING) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-aliasing=3") endif (WITH_WSTRICT_ALIASING) # with -fPIC check_c_compiler_flag("-fPIC" WITH_FPIC) if (WITH_FPIC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") endif (WITH_FPIC) check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG) if (WITH_STACK_PROTECTOR_STRONG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong") else (!WITH_STACK_PROTECTOR_STRONG) check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif (WITH_STACK_PROTECTOR) endif (WITH_STACK_PROTECTOR_STRONG) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel)) check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) if (WITH_FORTIFY_SOURCE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2") endif (WITH_FORTIFY_SOURCE) endif() endif() endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") # # Check for large filesystem support # if (CMAKE_SIZEOF_VOID_P MATCHES "8") # with large file support execute_process( COMMAND getconf LFS64_CFLAGS OUTPUT_VARIABLE _lfs_CFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) else (CMAKE_SIZEOF_VOID_P MATCHES "8") # with large file support execute_process( COMMAND getconf LFS_CFLAGS OUTPUT_VARIABLE _lfs_CFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) endif (CMAKE_SIZEOF_VOID_P MATCHES "8") if (_lfs_CFLAGS) string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}") endif (_lfs_CFLAGS) endif (UNIX AND NOT WIN32) if (MSVC) # Use secure functions by defaualt and suppress warnings about #"deprecated" functions set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") endif (MSVC) nss_wrapper-1.1.3/nss_wrapper.pl000755 001750 000144 00000024135 12247646107 016760 0ustar00asnusers000000 000000 #!/usr/bin/perl # use strict; use Getopt::Long; use Cwd qw(abs_path); my $opt_help = 0; my $opt_passwd_path = undef; my $opt_group_path = undef; my $opt_action = undef; my $opt_type = undef; my $opt_name = undef; my $opt_member = undef; my $opt_gid = 65534;# nogroup gid my $passwdfn = undef; my $groupfn = undef; my $memberfn = undef; my $actionfn = undef; sub passwd_add($$$$$); sub passwd_delete($$$$$); sub group_add($$$$$); sub group_delete($$$$$); sub member_add($$$$$); sub member_delete($$$$$); sub check_path($$); my $result = GetOptions( 'help|h|?' => \$opt_help, 'passwd_path=s' => \$opt_passwd_path, 'group_path=s' => \$opt_group_path, 'action=s' => \$opt_action, 'type=s' => \$opt_type, 'name=s' => \$opt_name, 'member=s' => \$opt_member, 'gid=i' => \$opt_gid ); sub usage($;$) { my ($ret, $msg) = @_; print $msg."\n\n" if defined($msg); print "usage: --help|-h|-? Show this help. --passwd_path Path of the 'passwd' file. --group_path Path of the 'group' file. --type 'passwd', 'group' and 'member' are supported. --action 'add' or 'delete'. --name The name of the object. --member The name of the member. --gid Primary Group ID for new users. "; exit($ret); } usage(1) if (not $result); usage(0) if ($opt_help); if (not defined($opt_action)) { usage(1, "missing: --action [add|delete]"); } if ($opt_action eq "add") { $passwdfn = \&passwd_add; $groupfn = \&group_add; $memberfn = \&member_add; } elsif ($opt_action eq "delete") { $passwdfn = \&passwd_delete; $groupfn = \&group_delete; $memberfn = \&member_delete; } else { usage(1, "invalid: --action [add|delete]: '$opt_action'"); } if (not defined($opt_type)) { usage(1, "missing: --type [passwd|group|member]"); } if ($opt_type eq "member" and not defined($opt_member)) { usage(1, "missing: --member "); } my $opt_fullpath_passwd; my $opt_fullpath_group; if ($opt_type eq "passwd") { $actionfn = $passwdfn; $opt_fullpath_passwd = check_path($opt_passwd_path, $opt_type); } elsif ($opt_type eq "group") { $actionfn = $groupfn; $opt_fullpath_group = check_path($opt_group_path, $opt_type); } elsif ($opt_type eq "member") { $actionfn = $memberfn; $opt_fullpath_passwd = check_path($opt_passwd_path, "passwd"); $opt_fullpath_group = check_path($opt_group_path, "group"); } else { usage(1, "invalid: --type [passwd|group]: '$opt_type'") } if (not defined($opt_name)) { usage(1, "missing: --name "); } if ($opt_name eq "") { usage(1, "invalid: --name "); } exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid); sub check_path($$) { my ($path,$type) = @_; if (not defined($path)) { usage(1, "missing: --$type\_path "); } if ($path eq "" or $path eq "/") { usage(1, "invalid: --$type\_path : '$path'"); } my $fullpath = abs_path($path); if (not defined($fullpath)) { usage(1, "invalid: --$type\_path : '$path'"); } return $fullpath; } sub passwd_add_entry($$); sub passwd_load($) { my ($path) = @_; my @lines; my $passwd = undef; open(PWD, "<$path") or die("Unable to open '$path' for read"); @lines = ; close(PWD); $passwd->{array} = (); $passwd->{name} = {}; $passwd->{uid} = {}; $passwd->{path} = $path; foreach my $line (@lines) { passwd_add_entry($passwd, $line); } return $passwd; } sub group_add_entry($$); sub group_load($) { my ($path) = @_; my @lines; my $group = undef; open(GROUP, "<$path") or die("Unable to open '$path' for read"); @lines = ; close(GROUP); $group->{array} = (); $group->{name} = {}; $group->{gid} = {}; $group->{path} = $path; foreach my $line (@lines) { group_add_entry($group, $line); } return $group; } sub passwd_lookup_name($$) { my ($passwd, $name) = @_; return undef unless defined($passwd->{name}{$name}); return $passwd->{name}{$name}; } sub group_lookup_name($$) { my ($group, $name) = @_; return undef unless defined($group->{name}{$name}); return $group->{name}{$name}; } sub passwd_lookup_uid($$) { my ($passwd, $uid) = @_; return undef unless defined($passwd->{uid}{$uid}); return $passwd->{uid}{$uid}; } sub group_lookup_gid($$) { my ($group, $gid) = @_; return undef unless defined($group->{gid}{$gid}); return $group->{gid}{$gid}; } sub passwd_get_free_uid($) { my ($passwd) = @_; my $uid = 1000; while (passwd_lookup_uid($passwd, $uid)) { $uid++; } return $uid; } sub group_get_free_gid($) { my ($group) = @_; my $gid = 1000; while (group_lookup_gid($group, $gid)) { $gid++; } return $gid; } sub passwd_add_entry($$) { my ($passwd, $str) = @_; chomp $str; my @e = split(':', $str); push(@{$passwd->{array}}, \@e); $passwd->{name}{$e[0]} = \@e; $passwd->{uid}{$e[2]} = \@e; } sub group_add_entry($$) { my ($group, $str) = @_; chomp $str; my @e = split(':', $str); push(@{$group->{array}}, \@e); $group->{name}{$e[0]} = \@e; $group->{gid}{$e[2]} = \@e; } sub passwd_remove_entry($$) { my ($passwd, $eref) = @_; for (my $i = 0; defined($passwd->{array}[$i]); $i++) { if ($eref == $passwd->{array}[$i]) { $passwd->{array}[$i] = undef; } } delete $passwd->{name}{${$eref}[0]}; delete $passwd->{uid}{${$eref}[2]}; } sub group_remove_entry($$) { my ($group, $eref) = @_; for (my $i = 0; defined($group->{array}[$i]); $i++) { if ($eref == $group->{array}[$i]) { $group->{array}[$i] = undef; } } delete $group->{name}{${$eref}[0]}; delete $group->{gid}{${$eref}[2]}; } sub group_add_member($$$) { my ($group, $eref, $username) = @_; my @members; my $str = @$eref[3] || undef; if ($str) { @members = split(",", $str); } foreach my $member (@members) { if ($member and $member eq $username) { die("account[$username] is already member of '@$eref[0]'"); } } push(@members, $username); my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @members); group_remove_entry($group, $eref); group_add_entry($group, $gwent); } sub group_delete_member($$$) { my ($group, $eref, $username) = @_; my @members = undef; my $str = @$eref[3] || undef; if ($str) { @members = split(",", $str); } my @new_members; my $removed = 0; foreach my $member (@members) { if ($member and $member ne $username) { push(@new_members, $member); } else { $removed = 1; } } if ($removed != 1) { die("account[$username] is not member of '@$eref[0]'"); } my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @new_members); group_remove_entry($group, $eref); group_add_entry($group, $gwent); } sub passwd_save($) { my ($passwd) = @_; my @lines = (); my $path = $passwd->{path}; my $tmppath = $path.$$; foreach my $eref (@{$passwd->{array}}) { next unless defined($eref); my $line = join(':', @{$eref}); push(@lines, $line); } open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write"); print PWD join("\n", @lines)."\n"; close(PWD); rename($tmppath, $path) or die("Unable to rename $tmppath => $path"); } sub group_save($) { my ($group) = @_; my @lines = (); my $path = $group->{path}; my $tmppath = $path.$$; foreach my $eref (@{$group->{array}}) { next unless defined($eref); my $line = join(':', @{$eref}); if (scalar(@{$eref}) == 3) { $line .= ":"; } push(@lines, $line); } open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write"); print GROUP join("\n", @lines)."\n"; close(GROUP); rename($tmppath, $path) or die("Unable to rename $tmppath => $path"); } sub passwd_add($$$$$) { my ($path, $dummy, $dummy2, $name, $gid) = @_; #print "passwd_add: '$name' in '$path'\n"; my $passwd = passwd_load($path); my $e = passwd_lookup_name($passwd, $name); die("account[$name] already exists in '$path'") if defined($e); my $uid = passwd_get_free_uid($passwd); my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false"; passwd_add_entry($passwd, $pwent); passwd_save($passwd); return 0; } sub passwd_delete($$$$$) { my ($path, $dummy, $dummy2, $name, $dummy3) = @_; #print "passwd_delete: '$name' in '$path'\n"; my $passwd = passwd_load($path); my $e = passwd_lookup_name($passwd, $name); die("account[$name] does not exists in '$path'") unless defined($e); passwd_remove_entry($passwd, $e); passwd_save($passwd); return 0; } sub group_add($$$$$) { my ($dummy, $dummy2, $path, $name, $dummy3) = @_; #print "group_add: '$name' in '$path'\n"; my $group = group_load($path); my $e = group_lookup_name($group, $name); die("group[$name] already exists in '$path'") if defined($e); my $gid = group_get_free_gid($group); my $gwent = $name.":x:".$gid.":".""; group_add_entry($group, $gwent); group_save($group); #printf("%d\n", $gid); return 0; } sub group_delete($$$$$) { my ($dummy, $dummy2, $path, $name, $dummy3) = @_; #print "group_delete: '$name' in '$path'\n"; my $group = group_load($path); my $e = group_lookup_name($group, $name); die("group[$name] does not exists in '$path'") unless defined($e); group_remove_entry($group, $e); group_save($group); return 0; } sub member_add($$$$$) { my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n"; my $group = group_load($group_path); my $g = group_lookup_name($group, $groupname); die("group[$groupname] does not exists in '$group_path'") unless defined($g); my $passwd = passwd_load($passwd_path); my $u = passwd_lookup_name($passwd, $username); die("account[$username] does not exists in '$passwd_path'") unless defined($u); group_add_member($group, $g, $username); group_save($group); return 0; } sub member_delete($$$$$) { my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n"; my $group = group_load($group_path); my $g = group_lookup_name($group, $groupname); die("group[$groupname] does not exists in '$group_path'") unless defined($g); my $passwd = passwd_load($passwd_path); my $u = passwd_lookup_name($passwd, $username); die("account[$username] does not exists in '$passwd_path'") unless defined($u); group_delete_member($group, $g, $username); group_save($group); return 0; } nss_wrapper-1.1.3/src/000755 001750 000144 00000000000 12672772135 014642 5ustar00asnusers000000 000000 nss_wrapper-1.1.3/src/CMakeLists.txt000644 001750 000144 00000001371 12620616655 017401 0ustar00asnusers000000 000000 project(libnss_wrapper C) include_directories(${CMAKE_BINARY_DIR}) add_library(nss_wrapper SHARED nss_wrapper.c) target_link_libraries(nss_wrapper ${NWRAP_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) if (BSD) add_definitions(-DBSD) endif (BSD) set_target_properties( nss_wrapper PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} ) install( TARGETS nss_wrapper RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ) # This needs to be at the end if (POLICY CMP0026) cmake_policy(SET CMP0026 OLD) endif() get_target_property(NWRAP_LOCATION nss_wrapper LOCATION) set(NSS_WRAPPER_LOCATION ${NWRAP_LOCATION} PARENT_SCOPE) nss_wrapper-1.1.3/src/nss_wrapper.c000644 001750 000144 00000365112 12672602321 017346 0ustar00asnusers000000 000000 /* * Copyright (C) Stefan Metzmacher 2007 * Copyright (C) Guenther Deschner 2009 * Copyright (C) Andreas Schneider 2013 * * 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 "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * 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 * Solaris */ #ifndef _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS #endif #include #include #ifdef HAVE_SHADOW_H #include #endif /* HAVE_SHADOW_H */ #include #include #include #include #if defined(HAVE_NSS_H) /* Linux and BSD */ #include typedef enum nss_status NSS_STATUS; #elif defined(HAVE_NSS_COMMON_H) /* Solaris */ #include #include #include typedef nss_status_t NSS_STATUS; # define NSS_STATUS_SUCCESS NSS_SUCCESS # define NSS_STATUS_NOTFOUND NSS_NOTFOUND # define NSS_STATUS_UNAVAIL NSS_UNAVAIL # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN #else # error "No nsswitch support detected" #endif #ifndef PTR_DIFF #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) #endif #ifndef _PUBLIC_ #define _PUBLIC_ #endif #ifndef EAI_NODATA #define EAI_NODATA EAI_NONAME #endif #ifndef EAI_ADDRFAMILY #define EAI_ADDRFAMILY EAI_FAMILY #endif #ifndef __STRING #define __STRING(x) #x #endif #ifndef __STRINGSTRING #define __STRINGSTRING(x) __STRING(x) #endif #ifndef __LINESTR__ #define __LINESTR__ __STRINGSTRING(__LINE__) #endif #ifndef __location__ #define __location__ __FILE__ ":" __LINESTR__ #endif #ifndef DNS_NAME_MAX #define DNS_NAME_MAX 255 #endif /* GCC have printf type attribute check. */ #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) #else #define PRINTF_ATTRIBUTE(a,b) #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */ #ifdef HAVE_DESTRUCTOR_ATTRIBUTE #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) #else #define DESTRUCTOR_ATTRIBUTE #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */ #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) #ifndef SAFE_FREE #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) #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 #ifdef HAVE_IPV6 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN #else #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN #endif #define NWRAP_LOCK(m) do { \ pthread_mutex_lock(&( m ## _mutex)); \ } while(0) #define NWRAP_UNLOCK(m) do { \ pthread_mutex_unlock(&( m ## _mutex)); \ } while(0) static bool nwrap_initialized = false; static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER; /* The mutex or accessing the id */ static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER; /* Add new global locks here please */ /* Also don't forget to add locks to * nwrap_init() function. */ # define NWRAP_LOCK_ALL do { \ NWRAP_LOCK(nwrap_initialized); \ NWRAP_LOCK(nwrap_global); \ NWRAP_LOCK(nwrap_gr_global); \ NWRAP_LOCK(nwrap_he_global); \ NWRAP_LOCK(nwrap_pw_global); \ NWRAP_LOCK(nwrap_sp_global); \ } while (0); # define NWRAP_UNLOCK_ALL do {\ NWRAP_UNLOCK(nwrap_sp_global); \ NWRAP_UNLOCK(nwrap_pw_global); \ NWRAP_UNLOCK(nwrap_he_global); \ NWRAP_UNLOCK(nwrap_gr_global); \ NWRAP_UNLOCK(nwrap_global); \ NWRAP_UNLOCK(nwrap_initialized); \ } while (0); static void nwrap_thread_prepare(void) { NWRAP_LOCK_ALL; } static void nwrap_thread_parent(void) { NWRAP_UNLOCK_ALL; } static void nwrap_thread_child(void) { NWRAP_UNLOCK_ALL; } enum nwrap_dbglvl_e { NWRAP_LOG_ERROR = 0, NWRAP_LOG_WARN, NWRAP_LOG_DEBUG, NWRAP_LOG_TRACE }; #ifdef NDEBUG # define NWRAP_LOG(...) #else static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__) static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) { char buffer[1024]; va_list va; const char *d; unsigned int lvl = 0; int pid = getpid(); d = getenv("NSS_WRAPPER_DEBUGLEVEL"); if (d != NULL) { lvl = atoi(d); } va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); if (lvl >= dbglvl) { switch (dbglvl) { case NWRAP_LOG_ERROR: fprintf(stderr, "NWRAP_ERROR(%d) - %s: %s\n", pid, func, buffer); break; case NWRAP_LOG_WARN: fprintf(stderr, "NWRAP_WARN(%d) - %s: %s\n", pid, func, buffer); break; case NWRAP_LOG_DEBUG: fprintf(stderr, "NWRAP_DEBUG(%d) - %s: %s\n", pid, func, buffer); break; case NWRAP_LOG_TRACE: fprintf(stderr, "NWRAP_TRACE(%d) - %s: %s\n", pid, func, buffer); break; } } } #endif /* NDEBUG NWRAP_LOG */ struct nwrap_libc_fns { struct passwd *(*_libc_getpwnam)(const char *name); int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); struct passwd *(*_libc_getpwuid)(uid_t uid); int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); void (*_libc_setpwent)(void); struct passwd *(*_libc_getpwent)(void); #ifdef HAVE_SOLARIS_GETPWENT_R struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen); #else int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); #endif void (*_libc_endpwent)(void); int (*_libc_initgroups)(const char *user, gid_t gid); struct group *(*_libc_getgrnam)(const char *name); int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result); struct group *(*_libc_getgrgid)(gid_t gid); int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result); void (*_libc_setgrent)(void); struct group *(*_libc_getgrent)(void); #ifdef HAVE_SOLARIS_GETGRENT_R struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen); #else int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result); #endif void (*_libc_endgrent)(void); int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups); void (*_libc_sethostent)(int stayopen); struct hostent *(*_libc_gethostent)(void); void (*_libc_endhostent)(void); struct hostent *(*_libc_gethostbyname)(const char *name); #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ struct hostent *(*_libc_gethostbyname2)(const char *name, int af); #endif struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type); int (*_libc_getaddrinfo)(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); int (*_libc_gethostname)(char *name, size_t len); #ifdef HAVE_GETHOSTBYNAME_R int (*_libc_gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #endif #ifdef HAVE_GETHOSTBYADDR_R int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #endif }; struct nwrap_module_nss_fns { NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_setpwent)(void); NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_endpwent)(void); NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_setgrent)(void); NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_endgrent)(void); }; struct nwrap_backend { const char *name; const char *so_path; void *so_handle; struct nwrap_ops *ops; struct nwrap_module_nss_fns *fns; }; struct nwrap_ops { struct passwd * (*nw_getpwnam)(struct nwrap_backend *b, const char *name); int (*nw_getpwnam_r)(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); struct passwd * (*nw_getpwuid)(struct nwrap_backend *b, uid_t uid); int (*nw_getpwuid_r)(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); void (*nw_setpwent)(struct nwrap_backend *b); struct passwd * (*nw_getpwent)(struct nwrap_backend *b); int (*nw_getpwent_r)(struct nwrap_backend *b, 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); struct group * (*nw_getgrnam)(struct nwrap_backend *b, const char *name); int (*nw_getgrnam_r)(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); struct group * (*nw_getgrgid)(struct nwrap_backend *b, gid_t gid); int (*nw_getgrgid_r)(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); void (*nw_setgrent)(struct nwrap_backend *b); struct group * (*nw_getgrent)(struct nwrap_backend *b); int (*nw_getgrent_r)(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); void (*nw_endgrent)(struct nwrap_backend *b); }; /* Public prototypes */ bool nss_wrapper_enabled(void); bool nss_wrapper_shadow_enabled(void); bool nss_wrapper_hosts_enabled(void); /* prototypes for files backend */ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, const char *name); static int nwrap_files_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b, uid_t uid); static int nwrap_files_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_files_setpwent(struct nwrap_backend *b); static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b); static int nwrap_files_getpwent_r(struct nwrap_backend *b, 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 struct group *nwrap_files_getgrnam(struct nwrap_backend *b, const char *name); static int nwrap_files_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_files_getgrgid(struct nwrap_backend *b, gid_t gid); static int nwrap_files_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_files_setgrent(struct nwrap_backend *b); static struct group *nwrap_files_getgrent(struct nwrap_backend *b); static int nwrap_files_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_files_endgrent(struct nwrap_backend *b); /* prototypes for module backend */ static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b); static int nwrap_module_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, const char *name); static int nwrap_module_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, uid_t uid); static int nwrap_module_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_module_setpwent(struct nwrap_backend *b); static void nwrap_module_endpwent(struct nwrap_backend *b); static struct group *nwrap_module_getgrent(struct nwrap_backend *b); static int nwrap_module_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, const char *name); static int nwrap_module_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, gid_t gid); static int nwrap_module_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, 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); struct nwrap_ops nwrap_files_ops = { .nw_getpwnam = nwrap_files_getpwnam, .nw_getpwnam_r = nwrap_files_getpwnam_r, .nw_getpwuid = nwrap_files_getpwuid, .nw_getpwuid_r = nwrap_files_getpwuid_r, .nw_setpwent = nwrap_files_setpwent, .nw_getpwent = nwrap_files_getpwent, .nw_getpwent_r = nwrap_files_getpwent_r, .nw_endpwent = nwrap_files_endpwent, .nw_initgroups = nwrap_files_initgroups, .nw_getgrnam = nwrap_files_getgrnam, .nw_getgrnam_r = nwrap_files_getgrnam_r, .nw_getgrgid = nwrap_files_getgrgid, .nw_getgrgid_r = nwrap_files_getgrgid_r, .nw_setgrent = nwrap_files_setgrent, .nw_getgrent = nwrap_files_getgrent, .nw_getgrent_r = nwrap_files_getgrent_r, .nw_endgrent = nwrap_files_endgrent, }; struct nwrap_ops nwrap_module_ops = { .nw_getpwnam = nwrap_module_getpwnam, .nw_getpwnam_r = nwrap_module_getpwnam_r, .nw_getpwuid = nwrap_module_getpwuid, .nw_getpwuid_r = nwrap_module_getpwuid_r, .nw_setpwent = nwrap_module_setpwent, .nw_getpwent = nwrap_module_getpwent, .nw_getpwent_r = nwrap_module_getpwent_r, .nw_endpwent = nwrap_module_endpwent, .nw_initgroups = nwrap_module_initgroups, .nw_getgrnam = nwrap_module_getgrnam, .nw_getgrnam_r = nwrap_module_getgrnam_r, .nw_getgrgid = nwrap_module_getgrgid, .nw_getgrgid_r = nwrap_module_getgrgid_r, .nw_setgrent = nwrap_module_setgrent, .nw_getgrent = nwrap_module_getgrent, .nw_getgrent_r = nwrap_module_getgrent_r, .nw_endgrent = nwrap_module_endgrent, }; struct nwrap_libc { void *handle; void *nsl_handle; void *sock_handle; struct nwrap_libc_fns *fns; }; struct nwrap_main { int num_backends; struct nwrap_backend *backends; struct nwrap_libc *libc; }; static struct nwrap_main *nwrap_main_global; static struct nwrap_main __nwrap_main_global; /* * PROTOTYPES */ static int nwrap_convert_he_ai(const struct hostent *he, unsigned short port, const struct addrinfo *hints, struct addrinfo **pai, bool skip_canonname); /* * VECTORS */ #define DEFAULT_VECTOR_CAPACITY 16 struct nwrap_vector { void **items; size_t count; size_t capacity; }; /* Macro returns pointer to first element of vector->items array. * * nwrap_vector is used as a memory backend which take care of * memory allocations and other stuff like memory growing. * nwrap_vectors should not be considered as some abstract structures. * On this level, vectors are more handy than direct realloc/malloc * calls. * * nwrap_vector->items is array inside nwrap_vector which can be * directly pointed by libc structure assembled by cwrap itself. * * EXAMPLE: * * 1) struct hostent contains char **h_addr_list element. * 2) nwrap_vector holds array of pointers to addresses. * It's easier to use vector to store results of * file parsing etc. * * Now, pretend that cwrap assembled struct hostent and * we need to set h_addr_list to point to nwrap_vector. * Idea behind is to shield users from internal nwrap_vector * implementation. * (Yes, not fully - array terminated by NULL is needed because * it's result expected by libc function caller.) * * * CODE EXAMPLE: * * struct hostent he; * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector)); * ... don't care about failed allocation now ... * * ... fill nwrap vector ... * * struct hostent he; * he.h_addr_list = nwrap_vector_head(vector); * */ #define nwrap_vector_head(vect) ((void *)((vect)->items)) #define nwrap_vector_foreach(item, vect, iter) \ for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \ item != NULL; \ (item) = (vect).items[++iter]) #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL) static inline bool nwrap_vector_init(struct nwrap_vector *const vector) { if (vector == NULL) { return false; } /* count is initialized by ZERO_STRUCTP */ ZERO_STRUCTP(vector); vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1)); if (vector->items == NULL) { return false; } vector->capacity = DEFAULT_VECTOR_CAPACITY; memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1)); return true; } static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item) { assert (vector != NULL); if (vector->items == NULL) { nwrap_vector_init(vector); } if (vector->count == vector->capacity) { /* Items array _MUST_ be NULL terminated because it's passed * as result to caller which expect NULL terminated array from libc. */ void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1)); if (items == NULL) { return false; } vector->items = items; /* Don't count ending NULL to capacity */ vector->capacity *= 2; } vector->items[vector->count] = item; vector->count += 1; vector->items[vector->count] = NULL; return true; } static bool nwrap_vector_merge(struct nwrap_vector *dst, struct nwrap_vector *src) { void **dst_items = NULL; size_t count; if (src->count == 0) { return true; } count = dst->count + src->count; /* We don't need reallocation if we have enough capacity. */ if (src->count > (dst->capacity - dst->count)) { dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *)); if (dst_items == NULL) { return false; } dst->items = dst_items; dst->capacity = count; } memcpy((void *)(((long *)dst->items) + dst->count), src->items, src->count * sizeof(void *)); dst->count = count; return true; } struct nwrap_cache { const char *path; int fd; FILE *fp; struct stat st; void *private_data; struct nwrap_vector lines; bool (*parse_line)(struct nwrap_cache *, char *line); void (*unload)(struct nwrap_cache *); }; /* passwd */ struct nwrap_pw { struct nwrap_cache *cache; struct passwd *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_pw; struct nwrap_pw nwrap_pw_global; static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_pw_unload(struct nwrap_cache *nwrap); /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) struct nwrap_sp { struct nwrap_cache *cache; struct spwd *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_sp; struct nwrap_sp nwrap_sp_global; static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_sp_unload(struct nwrap_cache *nwrap); #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* group */ struct nwrap_gr { struct nwrap_cache *cache; struct group *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_gr; struct nwrap_gr nwrap_gr_global; /* hosts */ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_he_unload(struct nwrap_cache *nwrap); struct nwrap_addrdata { unsigned char host_addr[16]; /* IPv4 or IPv6 address */ }; static size_t max_hostents = 100; struct nwrap_entdata { struct nwrap_addrdata addr; struct hostent ht; struct nwrap_vector nwrap_addrdata; ssize_t aliases_count; }; struct nwrap_entlist { struct nwrap_entlist *next; struct nwrap_entdata *ed; }; struct nwrap_he { struct nwrap_cache *cache; struct nwrap_vector entries; struct nwrap_vector lists; int num; int idx; }; static struct nwrap_cache __nwrap_cache_he; static struct nwrap_he nwrap_he_global; /********************************************************* * NWRAP PROTOTYPES *********************************************************/ static void nwrap_init(void); static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_gr_unload(struct nwrap_cache *nwrap); void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE; /********************************************************* * NWRAP LIBC LOADER FUNCTIONS *********************************************************/ enum nwrap_lib { NWRAP_LIBC, NWRAP_LIBNSL, NWRAP_LIBSOCKET, }; #ifndef NDEBUG static const char *nwrap_str_lib(enum nwrap_lib lib) { switch (lib) { case NWRAP_LIBC: return "libc"; case NWRAP_LIBNSL: return "libnsl"; case NWRAP_LIBSOCKET: return "libsocket"; } /* Compiler would warn us about unhandled enum value if we get here */ return "unknown"; } #endif static void *nwrap_load_lib_handle(enum nwrap_lib lib) { int flags = RTLD_LAZY; void *handle = NULL; int i; #ifdef RTLD_DEEPBIND flags |= RTLD_DEEPBIND; #endif switch (lib) { case NWRAP_LIBNSL: #ifdef HAVE_LIBNSL handle = nwrap_main_global->libc->nsl_handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libnsl.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->nsl_handle = handle; } break; #endif /* FALL TROUGH */ case NWRAP_LIBSOCKET: #ifdef HAVE_LIBSOCKET handle = nwrap_main_global->libc->sock_handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libsocket.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->sock_handle = handle; } break; #endif /* FALL TROUGH */ case NWRAP_LIBC: handle = nwrap_main_global->libc->handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libc.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->handle = handle; } break; } if (handle == NULL) { #ifdef RTLD_NEXT handle = nwrap_main_global->libc->handle = nwrap_main_global->libc->sock_handle = nwrap_main_global->libc->nsl_handle = RTLD_NEXT; #else NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to dlopen library: %s\n", dlerror()); exit(-1); #endif } return handle; } static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name) { void *handle; void *func; nwrap_init(); handle = nwrap_load_lib_handle(lib); func = dlsym(handle, fn_name); if (func == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to find %s: %s\n", fn_name, dlerror()); exit(-1); } NWRAP_LOG(NWRAP_LOG_TRACE, "Loaded %s from %s", fn_name, nwrap_str_lib(lib)); return func; } #define nwrap_load_lib_function(lib, fn_name) \ if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \ *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \ _nwrap_load_lib_function(lib, #fn_name); \ } /* INTERNAL HELPER FUNCTIONS */ static void nwrap_lines_unload(struct nwrap_cache *const nwrap) { size_t p; void *item; nwrap_vector_foreach(item, nwrap->lines, p) { /* Maybe some vectors were merged ... */ SAFE_FREE(item); } SAFE_FREE(nwrap->lines.items); ZERO_STRUCTP(&nwrap->lines); } /* * IMPORTANT * * Functions expeciall from libc need to be loaded individually, you can't load * all at once or gdb will segfault at startup. The same applies to valgrind and * has probably something todo with with the linker. * So we need load each function at the point it is called the first time. */ static struct passwd *libc_getpwnam(const char *name) { nwrap_load_lib_function(NWRAP_LIBC, getpwnam); return nwrap_main_global->libc->fns->_libc_getpwnam(name); } #ifdef HAVE_GETPWNAM_R static int libc_getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { #ifdef HAVE___POSIX_GETPWNAM_R if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) { *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) = _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r"); } #else nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r); #endif return nwrap_main_global->libc->fns->_libc_getpwnam_r(name, pwd, buf, buflen, result); } #endif static struct passwd *libc_getpwuid(uid_t uid) { nwrap_load_lib_function(NWRAP_LIBC, getpwuid); return nwrap_main_global->libc->fns->_libc_getpwuid(uid); } #ifdef HAVE_GETPWUID_R static int libc_getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { #ifdef HAVE___POSIX_GETPWUID_R if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) { *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) = _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r"); } #else nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r); #endif return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid, pwd, buf, buflen, result); } #endif static inline void str_tolower(char *dst, char *src) { register char *src_tmp = src; register char *dst_tmp = dst; while (*src_tmp != '\0') { *dst_tmp = tolower(*src_tmp); ++src_tmp; ++dst_tmp; } } static bool str_tolower_copy(char **dst_name, const char *const src_name) { char *h_name_lower; if ((dst_name == NULL) || (src_name == NULL)) { return false; } h_name_lower = strdup(src_name); if (h_name_lower == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup"); return false; } str_tolower(h_name_lower, h_name_lower); *dst_name = h_name_lower; return true; } static void libc_setpwent(void) { nwrap_load_lib_function(NWRAP_LIBC, setpwent); nwrap_main_global->libc->fns->_libc_setpwent(); } static struct passwd *libc_getpwent(void) { nwrap_load_lib_function(NWRAP_LIBC, getpwent); return nwrap_main_global->libc->fns->_libc_getpwent(); } #ifdef HAVE_SOLARIS_GETPWENT_R static struct passwd *libc_getpwent_r(struct passwd *pwdst, char *buf, int buflen) { nwrap_load_lib_function(NWRAP_LIBC, getpwent_r); return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst, buf, buflen); } #else /* HAVE_SOLARIS_GETPWENT_R */ static int libc_getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { nwrap_load_lib_function(NWRAP_LIBC, getpwent_r); return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst, buf, buflen, pwdstp); } #endif /* HAVE_SOLARIS_GETPWENT_R */ static void libc_endpwent(void) { nwrap_load_lib_function(NWRAP_LIBC, endpwent); nwrap_main_global->libc->fns->_libc_endpwent(); } static int libc_initgroups(const char *user, gid_t gid) { nwrap_load_lib_function(NWRAP_LIBC, initgroups); return nwrap_main_global->libc->fns->_libc_initgroups(user, gid); } static struct group *libc_getgrnam(const char *name) { nwrap_load_lib_function(NWRAP_LIBC, getgrnam); return nwrap_main_global->libc->fns->_libc_getgrnam(name); } #ifdef HAVE_GETGRNAM_R static int libc_getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result) { #ifdef HAVE___POSIX_GETGRNAM_R if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) { *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) = _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r"); } #else nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r); #endif return nwrap_main_global->libc->fns->_libc_getgrnam_r(name, grp, buf, buflen, result); } #endif static struct group *libc_getgrgid(gid_t gid) { nwrap_load_lib_function(NWRAP_LIBC, getgrgid); return nwrap_main_global->libc->fns->_libc_getgrgid(gid); } #ifdef HAVE_GETGRGID_R static int libc_getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result) { #ifdef HAVE___POSIX_GETGRGID_R if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) { *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) = _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r"); } #else nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r); #endif return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid, grp, buf, buflen, result); } #endif static void libc_setgrent(void) { nwrap_load_lib_function(NWRAP_LIBC, setgrent); nwrap_main_global->libc->fns->_libc_setgrent(); } static struct group *libc_getgrent(void) { nwrap_load_lib_function(NWRAP_LIBC, getgrent); return nwrap_main_global->libc->fns->_libc_getgrent(); } #ifdef HAVE_GETGRENT_R #ifdef HAVE_SOLARIS_GETGRENT_R static struct group *libc_getgrent_r(struct group *group, char *buf, size_t buflen) { nwrap_load_lib_function(NWRAP_LIBC, getgrent_r); return nwrap_main_global->libc->fns->_libc_getgrent_r(group, buf, buflen); } #else /* !HAVE_SOLARIS_GETGRENT_R */ static int libc_getgrent_r(struct group *group, char *buf, size_t buflen, struct group **result) { nwrap_load_lib_function(NWRAP_LIBC, getgrent_r); return nwrap_main_global->libc->fns->_libc_getgrent_r(group, buf, buflen, result); } #endif /* HAVE_SOLARIS_GETGRENT_R */ #endif /* HAVE_GETGRENT_R */ static void libc_endgrent(void) { nwrap_load_lib_function(NWRAP_LIBC, endgrent); nwrap_main_global->libc->fns->_libc_endgrent(); } #ifdef HAVE_GETGROUPLIST static int libc_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) { nwrap_load_lib_function(NWRAP_LIBC, getgrouplist); return nwrap_main_global->libc->fns->_libc_getgrouplist(user, group, groups, ngroups); } #endif static void libc_sethostent(int stayopen) { nwrap_load_lib_function(NWRAP_LIBNSL, sethostent); nwrap_main_global->libc->fns->_libc_sethostent(stayopen); } static struct hostent *libc_gethostent(void) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostent); return nwrap_main_global->libc->fns->_libc_gethostent(); } static void libc_endhostent(void) { nwrap_load_lib_function(NWRAP_LIBNSL, endhostent); nwrap_main_global->libc->fns->_libc_endhostent(); } static struct hostent *libc_gethostbyname(const char *name) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname); return nwrap_main_global->libc->fns->_libc_gethostbyname(name); } #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ static struct hostent *libc_gethostbyname2(const char *name, int af) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2); return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af); } #endif static struct hostent *libc_gethostbyaddr(const void *addr, socklen_t len, int type) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr); return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr, len, type); } static int libc_gethostname(char *name, size_t len) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostname); return nwrap_main_global->libc->fns->_libc_gethostname(name, len); } #ifdef HAVE_GETHOSTBYNAME_R static int libc_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r); return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } #endif #ifdef HAVE_GETHOSTBYADDR_R static int libc_gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r); return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop); } #endif static int libc_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo); return nwrap_main_global->libc->fns->_libc_getaddrinfo(node, service, hints, res); } static int libc_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo); return nwrap_main_global->libc->fns->_libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } /********************************************************* * NWRAP NSS MODULE LOADER FUNCTIONS *********************************************************/ static void *nwrap_load_module_fn(struct nwrap_backend *b, const char *fn_name) { void *res; char *s; if (!b->so_handle) { NWRAP_LOG(NWRAP_LOG_ERROR, "No handle"); return NULL; } if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return NULL; } res = dlsym(b->so_handle, s); if (!res) { NWRAP_LOG(NWRAP_LOG_ERROR, "Cannot find function %s in %s", s, b->so_path); } SAFE_FREE(s); return res; } static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b) { struct nwrap_module_nss_fns *fns; if (!b->so_handle) { return NULL; } fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns)); if (!fns) { return NULL; } *(void **)(&fns->_nss_getpwnam_r) = nwrap_load_module_fn(b, "getpwnam_r"); *(void **)(&fns->_nss_getpwuid_r) = nwrap_load_module_fn(b, "getpwuid_r"); *(void **)(&fns->_nss_setpwent) = nwrap_load_module_fn(b, "setpwent"); *(void **)(&fns->_nss_getpwent_r) = nwrap_load_module_fn(b, "getpwent_r"); *(void **)(&fns->_nss_endpwent) = nwrap_load_module_fn(b, "endpwent"); *(void **)(&fns->_nss_initgroups) = nwrap_load_module_fn(b, "initgroups_dyn"); *(void **)(&fns->_nss_getgrnam_r) = nwrap_load_module_fn(b, "getgrnam_r"); *(void **)(&fns->_nss_getgrgid_r)= nwrap_load_module_fn(b, "getgrgid_r"); *(void **)(&fns->_nss_setgrent) = nwrap_load_module_fn(b, "setgrent"); *(void **)(&fns->_nss_getgrent_r) = nwrap_load_module_fn(b, "getgrent_r"); *(void **)(&fns->_nss_endgrent) = nwrap_load_module_fn(b, "endgrent"); return fns; } static void *nwrap_load_module(const char *so_path) { void *h; if (!so_path || !strlen(so_path)) { return NULL; } h = dlopen(so_path, RTLD_LAZY); if (!h) { NWRAP_LOG(NWRAP_LOG_ERROR, "Cannot open shared library %s", so_path); return NULL; } return h; } static bool nwrap_module_init(const char *name, struct nwrap_ops *ops, const char *so_path, int *num_backends, struct nwrap_backend **backends) { struct nwrap_backend *b; *backends = (struct nwrap_backend *)realloc(*backends, sizeof(struct nwrap_backend) * ((*num_backends) + 1)); if (!*backends) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } b = &((*backends)[*num_backends]); b->name = name; b->ops = ops; b->so_path = so_path; if (so_path != NULL) { b->so_handle = nwrap_load_module(so_path); b->fns = nwrap_load_module_fns(b); if (b->fns == NULL) { return false; } } else { b->so_handle = NULL; b->fns = NULL; } (*num_backends)++; return true; } static void nwrap_libc_init(struct nwrap_main *r) { r->libc = malloc(sizeof(struct nwrap_libc)); if (r->libc == NULL) { printf("Failed to allocate memory for libc"); exit(-1); } ZERO_STRUCTP(r->libc); r->libc->fns = malloc(sizeof(struct nwrap_libc_fns)); if (r->libc->fns == NULL) { printf("Failed to allocate memory for libc functions"); exit(-1); } ZERO_STRUCTP(r->libc->fns); } static void nwrap_backend_init(struct nwrap_main *r) { const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH"); const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX"); r->num_backends = 0; r->backends = NULL; if (!nwrap_module_init("files", &nwrap_files_ops, NULL, &r->num_backends, &r->backends)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize 'files' backend"); return; } if (module_so_path != NULL && module_so_path[0] != '\0' && module_fn_name != NULL && module_fn_name[0] != '\0') { if (!nwrap_module_init(module_fn_name, &nwrap_module_ops, module_so_path, &r->num_backends, &r->backends)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize '%s' backend", module_fn_name); return; } } } static void nwrap_init(void) { const char *env; char *endptr; size_t max_hostents_tmp; NWRAP_LOCK(nwrap_initialized); if (nwrap_initialized) { NWRAP_UNLOCK(nwrap_initialized); return; } /* * Still holding nwrap_initialized lock here. * We don't use NWRAP_(UN)LOCK_ALL macros here because we * want to avoid overhead when other threads do their job. */ NWRAP_LOCK(nwrap_global); NWRAP_LOCK(nwrap_gr_global); NWRAP_LOCK(nwrap_he_global); NWRAP_LOCK(nwrap_pw_global); NWRAP_LOCK(nwrap_sp_global); nwrap_initialized = true; /* Initialize pthread_atfork handlers */ pthread_atfork(&nwrap_thread_prepare, &nwrap_thread_parent, &nwrap_thread_child); env = getenv("NSS_WRAPPER_MAX_HOSTENTS"); if (env != NULL) { max_hostents_tmp = (size_t)strtol(env, &endptr, 10); if (((env != '\0') && (endptr == '\0')) || (max_hostents_tmp == 0)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Error parsing NSS_WRAPPER_MAX_HOSTENTS " "value or value is too small. " "Using default value: %lu.", (unsigned long)max_hostents); } else { max_hostents = max_hostents_tmp; } } /* Initialize hash table */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Initializing hash table of size %lu items.", (unsigned long)max_hostents); if (hcreate(max_hostents) == 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table"); goto done; } nwrap_main_global = &__nwrap_main_global; nwrap_libc_init(nwrap_main_global); nwrap_backend_init(nwrap_main_global); /* passwd */ nwrap_pw_global.cache = &__nwrap_cache_pw; nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD"); nwrap_pw_global.cache->fp = NULL; nwrap_pw_global.cache->fd = -1; nwrap_pw_global.cache->private_data = &nwrap_pw_global; nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line; nwrap_pw_global.cache->unload = nwrap_pw_unload; /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) nwrap_sp_global.cache = &__nwrap_cache_sp; nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW"); nwrap_sp_global.cache->fp = NULL; nwrap_sp_global.cache->fd = -1; nwrap_sp_global.cache->private_data = &nwrap_sp_global; nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line; nwrap_sp_global.cache->unload = nwrap_sp_unload; #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* group */ nwrap_gr_global.cache = &__nwrap_cache_gr; nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP"); nwrap_gr_global.cache->fp = NULL; nwrap_gr_global.cache->fd = -1; nwrap_gr_global.cache->private_data = &nwrap_gr_global; nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line; nwrap_gr_global.cache->unload = nwrap_gr_unload; /* hosts */ nwrap_he_global.cache = &__nwrap_cache_he; nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS"); nwrap_he_global.cache->fp = NULL; nwrap_he_global.cache->fd = -1; nwrap_he_global.cache->private_data = &nwrap_he_global; nwrap_he_global.cache->parse_line = nwrap_he_parse_line; nwrap_he_global.cache->unload = nwrap_he_unload; done: /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */ NWRAP_UNLOCK_ALL; } bool nss_wrapper_enabled(void) { nwrap_init(); if (nwrap_pw_global.cache->path == NULL || nwrap_pw_global.cache->path[0] == '\0') { return false; } if (nwrap_gr_global.cache->path == NULL || nwrap_gr_global.cache->path[0] == '\0') { return false; } return true; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) bool nss_wrapper_shadow_enabled(void) { nwrap_init(); if (nwrap_sp_global.cache->path == NULL || nwrap_sp_global.cache->path[0] == '\0') { return false; } return true; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ bool nss_wrapper_hosts_enabled(void) { nwrap_init(); if (nwrap_he_global.cache->path == NULL || nwrap_he_global.cache->path[0] == '\0') { return false; } return true; } static bool nwrap_hostname_enabled(void) { nwrap_init(); if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) { return false; } return true; } static bool nwrap_parse_file(struct nwrap_cache *nwrap) { char *line = NULL; ssize_t n; /* Unused but getline needs it */ size_t len; bool ok; if (nwrap->st.st_size == 0) { NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0"); return true; } /* Support for 32-bit system I guess */ if (nwrap->st.st_size > INT32_MAX) { NWRAP_LOG(NWRAP_LOG_ERROR, "Size[%u] larger than INT32_MAX", (unsigned)nwrap->st.st_size); return false; } rewind(nwrap->fp); do { n = getline(&line, &len, nwrap->fp); if (n < 0) { SAFE_FREE(line); if (feof(nwrap->fp)) { break; } NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to read line from file: %s", nwrap->path); return false; } if (line[n - 1] == '\n') { line[n - 1] = '\0'; } if (line[0] == '\0') { SAFE_FREE(line); continue; } ok = nwrap->parse_line(nwrap, line); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to parse line file: %s", line); SAFE_FREE(line); return false; } /* Line is parsed without issues so add it to list */ ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add line to vector"); return false; } /* This forces getline to allocate new memory for line. */ line = NULL; } while (!feof(nwrap->fp)); return true; } static void nwrap_files_cache_unload(struct nwrap_cache *nwrap) { nwrap->unload(nwrap); nwrap_lines_unload(nwrap); } static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap) { struct stat st; int ret; bool ok; bool retried = false; assert(nwrap != NULL); reopen: if (nwrap->fd < 0) { nwrap->fp = fopen(nwrap->path, "re"); if (nwrap->fp == NULL) { nwrap->fd = -1; NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to open '%s' readonly %d:%s", nwrap->path, nwrap->fd, strerror(errno)); return false; } nwrap->fd = fileno(nwrap->fp); NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path); } ret = fstat(nwrap->fd, &st); if (ret != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "fstat(%s) - %d:%s", nwrap->path, ret, strerror(errno)); fclose(nwrap->fp); nwrap->fp = NULL; nwrap->fd = -1; return false; } if (retried == false && st.st_nlink == 0) { /* maybe someone has replaced the file... */ NWRAP_LOG(NWRAP_LOG_TRACE, "st_nlink == 0, reopen %s", nwrap->path); retried = true; memset(&nwrap->st, 0, sizeof(nwrap->st)); fclose(nwrap->fp); nwrap->fp = NULL; nwrap->fd = -1; goto reopen; } if (st.st_mtime == nwrap->st.st_mtime) { NWRAP_LOG(NWRAP_LOG_TRACE, "st_mtime[%u] hasn't changed, skip reload", (unsigned)st.st_mtime); return true; } NWRAP_LOG(NWRAP_LOG_TRACE, "st_mtime has changed [%u] => [%u], start reload", (unsigned)st.st_mtime, (unsigned)nwrap->st.st_mtime); nwrap->st = st; nwrap_files_cache_unload(nwrap); ok = nwrap_parse_file(nwrap); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path); nwrap_files_cache_unload(nwrap); return false; } NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path); return true; } /* * the caller has to call nwrap_unload() on failure */ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_pw *nwrap_pw; char *c; char *p; char *e; struct passwd *pw; size_t list_size; nwrap_pw = (struct nwrap_pw *)nwrap->private_data; list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1); pw = (struct passwd *)realloc(nwrap_pw->list, list_size); if (!pw) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%u) failed", (unsigned)list_size); return false; } nwrap_pw->list = pw; pw = &nwrap_pw->list[nwrap_pw->num]; c = line; /* name */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_name = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name); /* password */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_passwd = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd); /* uid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; pw->pw_uid = (uid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid); /* gid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; pw->pw_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid); #ifdef HAVE_STRUCT_PASSWD_PW_CLASS pw->pw_class = discard_const_p(char, ""); NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class); #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */ #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE pw->pw_change = 0; NWRAP_LOG(NWRAP_LOG_TRACE, "change[%lu]", (unsigned long)pw->pw_change); #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */ #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE pw->pw_expire = 0; NWRAP_LOG(NWRAP_LOG_TRACE, "expire[%lu]", (unsigned long)pw->pw_expire); #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */ /* gecos */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_gecos = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos); /* dir */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c); return false; } *p = '\0'; p++; pw->pw_dir = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir); /* shell */ pw->pw_shell = c; NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell); NWRAP_LOG(NWRAP_LOG_DEBUG, "Added user[%s:%s:%u:%u:%s:%s:%s]", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell); nwrap_pw->num++; return true; } static void nwrap_pw_unload(struct nwrap_cache *nwrap) { struct nwrap_pw *nwrap_pw; nwrap_pw = (struct nwrap_pw *)nwrap->private_data; SAFE_FREE(nwrap_pw->list); nwrap_pw->num = 0; nwrap_pw->idx = 0; } static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst, char *buf, size_t buflen, struct passwd **dstp) { char *first; char *last; off_t ofs; first = src->pw_name; last = src->pw_shell; while (*last) last++; ofs = PTR_DIFF(last + 1, first); if (ofs > (off_t) buflen) { return ERANGE; } memcpy(buf, first, ofs); ofs = PTR_DIFF(src->pw_name, first); dst->pw_name = buf + ofs; ofs = PTR_DIFF(src->pw_passwd, first); dst->pw_passwd = buf + ofs; dst->pw_uid = src->pw_uid; dst->pw_gid = src->pw_gid; ofs = PTR_DIFF(src->pw_gecos, first); dst->pw_gecos = buf + ofs; ofs = PTR_DIFF(src->pw_dir, first); dst->pw_dir = buf + ofs; ofs = PTR_DIFF(src->pw_shell, first); dst->pw_shell = buf + ofs; if (dstp) { *dstp = dst; } return 0; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_sp *nwrap_sp; struct spwd *sp; size_t list_size; char *c; char *e; char *p; nwrap_sp = (struct nwrap_sp *)nwrap->private_data; list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1); sp = (struct spwd *)realloc(nwrap_sp->list, list_size); if (sp == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%u) failed", (unsigned)list_size); return false; } nwrap_sp->list = sp; sp = &nwrap_sp->list[nwrap_sp->num]; c = line; /* name */ p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "name -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_namp = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp); /* pwd */ p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "pwd -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_pwdp = c; c = p; /* lstchg (long) */ if (c[0] == ':') { sp->sp_lstchg = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_lstchg = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* min (long) */ if (c[0] == ':') { sp->sp_min = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_min = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* max (long) */ if (c[0] == ':') { sp->sp_max = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_max = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* warn (long) */ if (c[0] == ':') { sp->sp_warn = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_warn = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* inact (long) */ if (c[0] == ':') { sp->sp_inact = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_inact = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* expire (long) */ if (c[0] == ':') { sp->sp_expire = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_expire = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; nwrap_sp->num++; return true; } static void nwrap_sp_unload(struct nwrap_cache *nwrap) { struct nwrap_sp *nwrap_sp; nwrap_sp = (struct nwrap_sp *)nwrap->private_data; SAFE_FREE(nwrap_sp->list); nwrap_sp->num = 0; nwrap_sp->idx = 0; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* * the caller has to call nwrap_unload() on failure */ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_gr *nwrap_gr; char *c; char *p; char *e; struct group *gr; size_t list_size; unsigned nummem; nwrap_gr = (struct nwrap_gr *)nwrap->private_data; list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1); gr = (struct group *)realloc(nwrap_gr->list, list_size); if (!gr) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed"); return false; } nwrap_gr->list = gr; gr = &nwrap_gr->list[nwrap_gr->num]; c = line; /* name */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; gr->gr_name = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name); /* password */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; gr->gr_passwd = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd); /* gid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; gr->gr_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid); /* members */ gr->gr_mem = (char **)malloc(sizeof(char *)); if (!gr->gr_mem) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } gr->gr_mem[0] = NULL; for(nummem=0; p; nummem++) { char **m; size_t m_size; c = p; p = strchr(c, ','); if (p) { *p = '\0'; p++; } if (strlen(c) == 0) { break; } m_size = sizeof(char *) * (nummem+2); m = (char **)realloc(gr->gr_mem, m_size); if (!m) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%zd) failed", m_size); return false; } gr->gr_mem = m; gr->gr_mem[nummem] = c; gr->gr_mem[nummem+1] = NULL; NWRAP_LOG(NWRAP_LOG_TRACE, "member[%u]: '%s'", nummem, gr->gr_mem[nummem]); } NWRAP_LOG(NWRAP_LOG_DEBUG, "Added group[%s:%s:%u:] with %u members", gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem); nwrap_gr->num++; return true; } static void nwrap_gr_unload(struct nwrap_cache *nwrap) { int i; struct nwrap_gr *nwrap_gr; nwrap_gr = (struct nwrap_gr *)nwrap->private_data; if (nwrap_gr->list) { for (i=0; i < nwrap_gr->num; i++) { SAFE_FREE(nwrap_gr->list[i].gr_mem); } SAFE_FREE(nwrap_gr->list); } nwrap_gr->num = 0; 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 *first; char **lastm; char *last = NULL; off_t ofsb; off_t ofsm; off_t ofs; unsigned i; first = src->gr_name; lastm = src->gr_mem; while (*lastm) { last = *lastm; lastm++; } if (last == NULL) { last = src->gr_passwd; } while (*last) last++; ofsb = PTR_DIFF(last + 1, first); ofsm = PTR_DIFF(lastm + 1, src->gr_mem); if ((ofsb + ofsm) > (off_t) buflen) { return ERANGE; } memcpy(buf, first, ofsb); memcpy(buf + ofsb, src->gr_mem, ofsm); ofs = PTR_DIFF(src->gr_name, first); dst->gr_name = buf + ofs; ofs = PTR_DIFF(src->gr_passwd, first); dst->gr_passwd = buf + ofs; dst->gr_gid = src->gr_gid; dst->gr_mem = (char **)(buf + ofsb); for (i=0; src->gr_mem[i]; i++) { ofs = PTR_DIFF(src->gr_mem[i], first); dst->gr_mem[i] = buf + ofs; } if (dstp) { *dstp = dst; } return 0; } static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed) { struct nwrap_entlist *el; if (ed == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "entry is NULL, can't create list item"); return NULL; } el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist)); if (el == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed"); return NULL; } el->next = NULL; el->ed = ed; return el; } static bool nwrap_ed_inventarize_add_new(char *const h_name, struct nwrap_entdata *const ed) { ENTRY e; ENTRY *p; struct nwrap_entlist *el; bool ok; if (h_name == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add"); return false; } el = nwrap_entlist_init(ed); if (el == NULL) { return false; } e.key = h_name; e.data = (void *)el; p = hsearch(e, ENTER); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full!"); return false; } ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to add list entry to vector."); return false; } return true; } static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed, struct nwrap_entlist *const el) { struct nwrap_entlist *cursor; struct nwrap_entlist *el_new; if (el == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add"); return false; } for (cursor = el; cursor->next != NULL; cursor = cursor->next) { if (cursor->ed == ed) { /* The entry already exists in this list. */ return true; } } if (cursor->ed == ed) { /* The entry already exists in this list. */ return true; } el_new = nwrap_entlist_init(ed); if (el_new == NULL) { return false; } cursor->next = el_new; return true; } static bool nwrap_ed_inventarize(char *const name, struct nwrap_entdata *const ed) { ENTRY e; ENTRY *p; bool ok; e.key = name; e.data = NULL; NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key); p = hsearch(e, FIND); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name); ok = nwrap_ed_inventarize_add_new(name, ed); } else { struct nwrap_entlist *el = (struct nwrap_entlist *)p->data; NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name); ok = nwrap_ed_inventarize_add_to_existing(ed, el); } return ok; } static bool nwrap_add_hname(struct nwrap_entdata *const ed) { char *const h_name = (char *const)(ed->ht.h_name); unsigned i; bool ok; ok = nwrap_ed_inventarize(h_name, ed); if (!ok) { return false; } if (ed->ht.h_aliases == NULL) { return true; } /* Itemize aliases */ for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) { char *h_name_alias; h_name_alias = ed->ht.h_aliases[i]; NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias); if (!nwrap_ed_inventarize(h_name_alias, ed)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add alias: %s", h_name_alias); return false; } } return true; } static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data; bool do_aliases = true; ssize_t aliases_count = 0; char *p; char *i; char *n; char *ip; bool ok; struct nwrap_entdata *ed = (struct nwrap_entdata *) malloc(sizeof(struct nwrap_entdata)); if (ed == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for nwrap_entdata"); return false; } ZERO_STRUCTP(ed); i = line; /* * IP */ /* Walk to first char */ for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } } for (i = p; !isspace((int)*p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } } *p = '\0'; if (inet_pton(AF_INET, i, ed->addr.host_addr)) { ed->ht.h_addrtype = AF_INET; ed->ht.h_length = 4; #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) { ed->ht.h_addrtype = AF_INET6; ed->ht.h_length = 16; #endif } else { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } ip = i; ok = nwrap_vector_add_item(&(ed->nwrap_addrdata), (void *const)ed->addr.host_addr); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector"); free(ed); return false; } ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata); p++; /* * FQDN */ /* Walk to first char */ for (n = p; *p != '_' && !isalnum((int) *p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, n); free(ed); return false; } } for (n = p; !isspace((int)*p); p++) { if (*p == '\0') { do_aliases = false; break; } } *p = '\0'; /* Convert to lowercase. This operate on same memory region */ str_tolower(n, n); ed->ht.h_name = n; /* glib's getent always dereferences he->h_aliases */ ed->ht.h_aliases = malloc(sizeof(char *)); if (ed->ht.h_aliases == NULL) { free(ed); return false; } ed->ht.h_aliases[0] = NULL; /* * Aliases */ while (do_aliases) { char **aliases; char *a; p++; /* Walk to first char */ for (a = p; *p != '_' && !isalnum((int) *p); p++) { if (*p == '\0') { do_aliases = false; break; } } /* Only trailing spaces are left */ if (!do_aliases) { break; } for (a = p; !isspace((int)*p); p++) { if (*p == '\0') { do_aliases = false; break; } } *p = '\0'; aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2)); if (aliases == NULL) { free(ed); return false; } ed->ht.h_aliases = aliases; str_tolower(a, a); aliases[aliases_count] = a; aliases[aliases_count + 1] = NULL; aliases_count += 1; } ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector"); free(ed); return false; } ed->aliases_count = aliases_count; /* Inventarize item */ ok = nwrap_add_hname(ed); if (!ok) { return false; } ok = nwrap_ed_inventarize(ip, ed); if (!ok) { return false; } nwrap_he->num++; return true; } static void nwrap_he_unload(struct nwrap_cache *nwrap) { struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data; struct nwrap_entdata *ed; struct nwrap_entlist *el; size_t i; int rc; nwrap_vector_foreach (ed, nwrap_he->entries, i) { SAFE_FREE(ed->nwrap_addrdata.items); SAFE_FREE(ed->ht.h_aliases); SAFE_FREE(ed); } SAFE_FREE(nwrap_he->entries.items); nwrap_he->entries.count = nwrap_he->entries.capacity = 0; nwrap_vector_foreach(el, nwrap_he->lists, i) { while (el != NULL) { struct nwrap_entlist *el_next; el_next = el->next; SAFE_FREE(el); el = el_next; } } SAFE_FREE(nwrap_he->lists.items); nwrap_he->lists.count = nwrap_he->lists.capacity = 0; nwrap_he->num = 0; nwrap_he->idx = 0; /* * If we unload the file, the pointers in the hash table point to * invalid memory. So we need to destroy the hash table and recreate * it. */ hdestroy(); rc = hcreate(max_hostents); if (rc == 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table"); exit(-1); } } /* user functions */ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, const char *name) { int i; bool ok; (void) b; /* unused */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name); ok = nwrap_files_cache_reload(nwrap_pw_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file"); return NULL; } for (i=0; i= nwrap_pw_global.num) { errno = ENOENT; return NULL; } pw = &nwrap_pw_global.list[nwrap_pw_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return user[%s] uid[%u]", pw->pw_name, pw->pw_uid); return pw; } static int nwrap_files_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { struct passwd *pw; pw = nwrap_files_getpwent(b); if (!pw) { if (errno == 0) { return ENOENT; } return errno; } return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp); } static void nwrap_files_endpwent(struct nwrap_backend *b) { (void) b; /* unused */ nwrap_pw_global.idx = 0; } /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) #ifdef HAVE_SETSPENT static void nwrap_files_setspent(void) { nwrap_sp_global.idx = 0; } static struct spwd *nwrap_files_getspent(void) { struct spwd *sp; if (nwrap_sp_global.idx == 0) { bool ok; ok = nwrap_files_cache_reload(nwrap_sp_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file"); return NULL; } } if (nwrap_sp_global.idx >= nwrap_sp_global.num) { errno = ENOENT; return NULL; } sp = &nwrap_sp_global.list[nwrap_sp_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return user[%s]", sp->sp_namp); return sp; } static void nwrap_files_endspent(void) { nwrap_sp_global.idx = 0; } #endif /* HAVE_SETSPENT */ static struct spwd *nwrap_files_getspnam(const char *name) { int i; bool ok; NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name); ok = nwrap_files_cache_reload(nwrap_sp_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file"); return NULL; } for (i=0; igr_name); for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { if (group != grp->gr_gid && (strcmp(user, grp->gr_mem[i]) == 0)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "%s is member of %s", 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; } groups[size] = grp->gr_gid; size++; } } } 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; } /* group functions */ static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, const char *name) { int i; bool ok; (void) b; /* unused */ ok = nwrap_files_cache_reload(nwrap_gr_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file"); return NULL; } for (i=0; i= nwrap_gr_global.num) { errno = ENOENT; return NULL; } gr = &nwrap_gr_global.list[nwrap_gr_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return group[%s] gid[%u]", gr->gr_name, gr->gr_gid); return gr; } static int nwrap_files_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { struct group *gr; gr = nwrap_files_getgrent(b); if (!gr) { if (errno == 0) { return ENOENT; } return errno; } return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp); } static void nwrap_files_endgrent(struct nwrap_backend *b) { (void) b; /* unused */ nwrap_gr_global.idx = 0; } /* hosts functions */ static int nwrap_files_gethostbyname(const char *name, int af, struct hostent *result, struct nwrap_vector *addr_list) { struct nwrap_entlist *el; struct hostent *he; char *h_name_lower; ENTRY e; ENTRY *e_p; char canon_name[DNS_NAME_MAX] = { 0 }; size_t name_len; bool he_found = false; bool ok; ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); goto no_ent; } name_len = strlen(name); if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') { strncpy(canon_name, name, name_len - 1); name = canon_name; } if (!str_tolower_copy(&h_name_lower, name)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while converting to lower case"); goto no_ent; } /* Look at hash table for element */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower); e.key = h_name_lower; e.data = NULL; e_p = hsearch(e, FIND); if (e_p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower); SAFE_FREE(h_name_lower); goto no_ent; } SAFE_FREE(h_name_lower); /* Always cleanup vector and results */ if (!nwrap_vector_is_initialized(addr_list)) { if (!nwrap_vector_init(addr_list)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Unable to initialize memory for addr_list vector"); goto no_ent; } } else { /* When vector is initialized data are valid no more. * Quick way how to free vector is: */ addr_list->count = 0; } /* Iterate through results */ for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next) { he = &(el->ed->ht); /* Filter by address familiy if provided */ if (af != AF_UNSPEC && he->h_addrtype != af) { continue; } /* * GLIBC HACK? * glibc doesn't return ipv6 addresses when AF_UNSPEC is used */ if (af == AF_UNSPEC && he->h_addrtype != AF_INET) { continue; } if (!he_found) { memcpy(result, he, sizeof(struct hostent)); NWRAP_LOG(NWRAP_LOG_DEBUG, "Name found. Returning record for %s", he->h_name); he_found = true; } nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata); result->h_addr_list = nwrap_vector_head(addr_list); } if (he_found) { return 0; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Name found in database. No records matches type."); no_ent: errno = ENOENT; return -1; } #ifdef HAVE_GETHOSTBYNAME_R static int nwrap_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector)); int rc; if (addr_list == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for address list"); errno = ENOENT; return -1; } ZERO_STRUCTP(addr_list); rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list); if (rc == -1) { *h_errnop = h_errno; if (addr_list->items != NULL) { free(addr_list->items); } SAFE_FREE(addr_list); errno = ENOENT; return -1; } if (buflen < (addr_list->count * sizeof(void *))) { SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); return ERANGE; } /* Copy all to user provided buffer and change * pointers in returned structure. * +1 is for ending NULL pointer. */ memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *)); free(addr_list->items); free(addr_list); ret->h_addr_list = (char **)buf; *result = ret; return 0; } int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } #endif static int nwrap_files_getaddrinfo(const char *name, unsigned short port, const struct addrinfo *hints, struct addrinfo **ai) { struct nwrap_entlist *el; struct hostent *he; struct addrinfo *ai_head = NULL; struct addrinfo *ai_cur = NULL; char *h_name_lower; size_t name_len; char canon_name[DNS_NAME_MAX] = { 0 }; bool skip_canonname = false; ENTRY e = { .key = NULL, }; ENTRY *e_p = NULL; int rc; bool ok; ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); return EAI_SYSTEM; } name_len = strlen(name); if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') { strncpy(canon_name, name, name_len - 1); name = canon_name; } if (!str_tolower_copy(&h_name_lower, name)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while converting to lower case"); return EAI_MEMORY; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower); e.key = h_name_lower; e.data = NULL; e_p = hsearch(e, FIND); if (e_p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower); SAFE_FREE(h_name_lower); errno = ENOENT; return EAI_NONAME; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower); SAFE_FREE(h_name_lower); rc = EAI_NONAME; for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next) { int rc2; struct addrinfo *ai_new = NULL; he = &(el->ed->ht); if (hints->ai_family != AF_UNSPEC && he->h_addrtype != hints->ai_family) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Entry found but with wrong AF - " "remembering EAI_ADDRINFO."); rc = EAI_ADDRFAMILY; continue; } /* Function allocates memory and returns it in ai. */ rc2 = nwrap_convert_he_ai(he, port, hints, &ai_new, skip_canonname); if (rc2 != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai"); if (ai_head != NULL) { freeaddrinfo(ai_head); } return rc2; } skip_canonname = true; if (ai_head == NULL) { ai_head = ai_new; } if (ai_cur != NULL) { ai_cur->ai_next = ai_new; } ai_cur = ai_new; } if (ai_head != NULL) { rc = 0; } *ai = ai_head; return rc; } static struct hostent *nwrap_files_gethostbyaddr(const void *addr, socklen_t len, int type) { struct hostent *he; char ip[NWRAP_INET_ADDRSTRLEN] = {0}; struct nwrap_entdata *ed; const char *a; size_t i; bool ok; (void) len; /* unused */ ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); return NULL; } a = inet_ntop(type, addr, ip, sizeof(ip)); if (a == NULL) { errno = EINVAL; return NULL; } nwrap_vector_foreach(ed, nwrap_he_global.entries, i) { he = &(ed->ht); if (he->h_addrtype != type) { continue; } if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) { return he; } } errno = ENOENT; return NULL; } #ifdef HAVE_GETHOSTBYADDR_R static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { *result = nwrap_files_gethostbyaddr(addr, len, type); if (*result != NULL) { memset(buf, '\0', buflen); *ret = **result; return 0; } else { *h_errnop = h_errno; return -1; } } int gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop); } return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop); } #endif /* hosts enum functions */ static void nwrap_files_sethostent(void) { nwrap_he_global.idx = 0; } static struct hostent *nwrap_files_gethostent(void) { struct hostent *he; if (nwrap_he_global.idx == 0) { bool ok; ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file"); return NULL; } } if (nwrap_he_global.idx >= nwrap_he_global.num) { errno = ENOENT; return NULL; } he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht; NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name); return he; } static void nwrap_files_endhostent(void) { nwrap_he_global.idx = 0; } /* * module backend */ static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, const char *name) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (!b->fns->_nss_getpwnam_r) { return NULL; } status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; (void) b; /* unused */ (void) pwdst; /* unused */ (void) pwdstp; /* unused */ if (!b->fns->_nss_getpwnam_r) { return NSS_STATUS_NOTFOUND; } ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, uid_t uid) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (!b->fns->_nss_getpwuid_r) { return NULL; } status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; (void) pwdstp; /* unused */ if (!b->fns->_nss_getpwuid_r) { return ENOENT; } ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_setpwent(struct nwrap_backend *b) { if (!b->fns->_nss_setpwent) { return; } b->fns->_nss_setpwent(); } static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (!b->fns->_nss_getpwent_r) { return NULL; } status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; (void) pwdstp; /* unused */ if (!b->fns->_nss_getpwent_r) { return ENOENT; } ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_endpwent(struct nwrap_backend *b) { if (!b->fns->_nss_endpwent) { return; } b->fns->_nss_endpwent(); } static int nwrap_module_initgroups(struct nwrap_backend *b, const char *user, gid_t group) { gid_t *groups; long int start; long int size; if (!b->fns->_nss_initgroups) { return NSS_STATUS_UNAVAIL; } return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno); } static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, const char *name) { static struct group grp; static char *buf; static int buflen = 1000; NSS_STATUS status; if (!b->fns->_nss_getgrnam_r) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; (void) grdstp; /* unused */ if (!b->fns->_nss_getgrnam_r) { return ENOENT; } ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, gid_t gid) { static struct group grp; static char *buf; static int buflen = 1000; NSS_STATUS status; if (!b->fns->_nss_getgrgid_r) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; (void) grdstp; /* unused */ if (!b->fns->_nss_getgrgid_r) { return ENOENT; } ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_setgrent(struct nwrap_backend *b) { if (!b->fns->_nss_setgrent) { return; } b->fns->_nss_setgrent(); } static struct group *nwrap_module_getgrent(struct nwrap_backend *b) { static struct group grp; static char *buf; static int buflen = 1024; NSS_STATUS status; if (!b->fns->_nss_getgrent_r) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; (void) grdstp; /* unused */ if (!b->fns->_nss_getgrent_r) { return ENOENT; } ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_endgrent(struct nwrap_backend *b) { if (!b->fns->_nss_endgrent) { return; } b->fns->_nss_endgrent(); } /**************************************************************************** * GETPWNAM ***************************************************************************/ static struct passwd *nwrap_getpwnam(const char *name) { int i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwnam(b, name); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwnam(const char *name) { if (!nss_wrapper_enabled()) { return libc_getpwnam(name); } return nwrap_getpwnam(name); } /**************************************************************************** * GETPWNAM_R ***************************************************************************/ static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int i,ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETPWNAM_R # ifdef HAVE_SOLARIS_GETPWNAM_R int getpwnam_r(const char *name, struct passwd *pwdst, char *buf, int buflen, struct passwd **pwdstp) # else /* HAVE_SOLARIS_GETPWNAM_R */ int getpwnam_r(const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) # endif /* HAVE_SOLARIS_GETPWNAM_R */ { if (!nss_wrapper_enabled()) { return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp); } return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp); } #endif /**************************************************************************** * GETPWUID ***************************************************************************/ static struct passwd *nwrap_getpwuid(uid_t uid) { int i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwuid(b, uid); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwuid(uid_t uid) { if (!nss_wrapper_enabled()) { return libc_getpwuid(uid); } return nwrap_getpwuid(uid); } /**************************************************************************** * GETPWUID_R ***************************************************************************/ static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int i,ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_SOLARIS_GETPWUID_R int getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, int buflen, struct passwd **pwdstp) #else int getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) #endif { if (!nss_wrapper_enabled()) { return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); } return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); } /**************************************************************************** * SETPWENT ***************************************************************************/ static void nwrap_setpwent(void) { int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_setpwent(b); } } void setpwent(void) { if (!nss_wrapper_enabled()) { libc_setpwent(); return; } nwrap_setpwent(); } /**************************************************************************** * GETPWENT ***************************************************************************/ static struct passwd *nwrap_getpwent(void) { int i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwent(b); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwent(void) { if (!nss_wrapper_enabled()) { return libc_getpwent(); } return nwrap_getpwent(); } /**************************************************************************** * GETPWENT_R ***************************************************************************/ static int nwrap_getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int i,ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_SOLARIS_GETPWENT_R struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen) { struct passwd *pwdstp = NULL; int rc; if (!nss_wrapper_enabled()) { return libc_getpwent_r(pwdst, buf, buflen); } rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp); if (rc < 0) { return NULL; } return pwdstp; } #else /* HAVE_SOLARIS_GETPWENT_R */ int getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { if (!nss_wrapper_enabled()) { return libc_getpwent_r(pwdst, buf, buflen, pwdstp); } return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp); } #endif /* HAVE_SOLARIS_GETPWENT_R */ /**************************************************************************** * ENDPWENT ***************************************************************************/ static void nwrap_endpwent(void) { int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_endpwent(b); } } void endpwent(void) { if (!nss_wrapper_enabled()) { libc_endpwent(); return; } nwrap_endpwent(); } /**************************************************************************** * INITGROUPS ***************************************************************************/ static int nwrap_initgroups(const char *user, gid_t group) { int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; int rc; rc = b->ops->nw_initgroups(b, user, group); if (rc == 0) { return 0; } } errno = ENOENT; return -1; } int initgroups(const char *user, gid_t group) { if (!nss_wrapper_enabled()) { return libc_initgroups(user, group); } return nwrap_initgroups(user, group); } /**************************************************************************** * GETGRNAM ***************************************************************************/ static struct group *nwrap_getgrnam(const char *name) { int i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrnam(b, name); if (grp) { return grp; } } return NULL; } struct group *getgrnam(const char *name) { if (!nss_wrapper_enabled()) { return libc_getgrnam(name); } return nwrap_getgrnam(name); } /**************************************************************************** * GETGRNAM_R ***************************************************************************/ static int nwrap_getgrnam_r(const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int i, ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETGRNAM_R # ifdef HAVE_SOLARIS_GETGRNAM_R int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp) # else /* HAVE_SOLARIS_GETGRNAM_R */ int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **pgrp) # endif /* HAVE_SOLARIS_GETGRNAM_R */ { if (!nss_wrapper_enabled()) { return libc_getgrnam_r(name, grp, buf, buflen, pgrp); } return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp); } #endif /* HAVE_GETGRNAM_R */ /**************************************************************************** * GETGRGID ***************************************************************************/ static struct group *nwrap_getgrgid(gid_t gid) { int i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrgid(b, gid); if (grp) { return grp; } } return NULL; } struct group *getgrgid(gid_t gid) { if (!nss_wrapper_enabled()) { return libc_getgrgid(gid); } return nwrap_getgrgid(gid); } /**************************************************************************** * GETGRGID_R ***************************************************************************/ static int nwrap_getgrgid_r(gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int i,ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETGRGID_R # ifdef HAVE_SOLARIS_GETGRGID_R int getgrgid_r(gid_t gid, struct group *grdst, char *buf, int buflen, struct group **grdstp) # else /* HAVE_SOLARIS_GETGRGID_R */ int getgrgid_r(gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) # endif /* HAVE_SOLARIS_GETGRGID_R */ { if (!nss_wrapper_enabled()) { return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp); } return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp); } #endif /**************************************************************************** * SETGRENT ***************************************************************************/ static void nwrap_setgrent(void) { int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_setgrent(b); } } #ifdef HAVE_BSD_SETGRENT int setgrent(void) #else void setgrent(void) #endif { if (!nss_wrapper_enabled()) { libc_setgrent(); goto out; } nwrap_setgrent(); out: #ifdef HAVE_BSD_SETGRENT return 0; #else return; #endif } /**************************************************************************** * GETGRENT ***************************************************************************/ static struct group *nwrap_getgrent(void) { int i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrent(b); if (grp) { return grp; } } return NULL; } struct group *getgrent(void) { if (!nss_wrapper_enabled()) { return libc_getgrent(); } return nwrap_getgrent(); } /**************************************************************************** * GETGRENT_R ***************************************************************************/ static int nwrap_getgrent_r(struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int i,ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_SOLARIS_GETGRENT_R struct group *getgrent_r(struct group *src, char *buf, int buflen) { struct group *grdstp = NULL; int rc; if (!nss_wrapper_enabled()) { return libc_getgrent_r(src, buf, buflen); } rc = nwrap_getgrent_r(src, buf, buflen, &grdstp); if (rc < 0) { return NULL; } return grdstp; } #else /* HAVE_SOLARIS_GETGRENT_R */ int getgrent_r(struct group *src, char *buf, size_t buflen, struct group **grdstp) { if (!nss_wrapper_enabled()) { return libc_getgrent_r(src, buf, buflen, grdstp); } return nwrap_getgrent_r(src, buf, buflen, grdstp); } #endif /* HAVE_SOLARIS_GETGRENT_R */ /**************************************************************************** * ENDGRENT ***************************************************************************/ static void nwrap_endgrent(void) { int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_endgrent(b); } } void endgrent(void) { if (!nss_wrapper_enabled()) { libc_endgrent(); return; } nwrap_endgrent(); } /**************************************************************************** * GETGROUPLIST ***************************************************************************/ #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++) { if (group != grp->gr_gid && (strcmp(user, grp->gr_mem[i]) == 0)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "%s is member of %s", user, grp->gr_name); 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; count++; } } } nwrap_endgrent(); NWRAP_LOG(NWRAP_LOG_DEBUG, "%s is member of %d groups", user, *ngroups); if (*ngroups < count) { *ngroups = count; free(groups_tmp); return -1; } *ngroups = count; memcpy(groups, groups_tmp, count * sizeof(gid_t)); free(groups_tmp); 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); } return nwrap_getgrouplist(user, group, groups, ngroups); } #endif /********************************************************** * SHADOW **********************************************************/ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) #ifdef HAVE_SETSPENT static void nwrap_setspent(void) { nwrap_files_setspent(); } void setspent(void) { if (!nss_wrapper_shadow_enabled()) { return; } nwrap_setspent(); } static struct spwd *nwrap_getspent(void) { return nwrap_files_getspent(); } struct spwd *getspent(void) { if (!nss_wrapper_shadow_enabled()) { return NULL; } return nwrap_getspent(); } static void nwrap_endspent(void) { nwrap_files_endspent(); } void endspent(void) { if (!nss_wrapper_shadow_enabled()) { return; } nwrap_endspent(); } #endif /* HAVE_SETSPENT */ static struct spwd *nwrap_getspnam(const char *name) { return nwrap_files_getspnam(name); } struct spwd *getspnam(const char *name) { if (!nss_wrapper_shadow_enabled()) { return NULL; } return nwrap_getspnam(name); } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /********************************************************** * NETDB **********************************************************/ static void nwrap_sethostent(int stayopen) { (void) stayopen; /* ignored */ nwrap_files_sethostent(); } #ifdef HAVE_SOLARIS_SETHOSTENT int sethostent(int stayopen) { if (!nss_wrapper_hosts_enabled()) { libc_sethostent(stayopen); return 0; } nwrap_sethostent(stayopen); return 0; } #else /* HAVE_SOLARIS_SETHOSTENT */ void sethostent(int stayopen) { if (!nss_wrapper_hosts_enabled()) { libc_sethostent(stayopen); return; } nwrap_sethostent(stayopen); } #endif /* HAVE_SOLARIS_SETHOSTENT */ static struct hostent *nwrap_gethostent(void) { return nwrap_files_gethostent(); } struct hostent *gethostent(void) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostent(); } return nwrap_gethostent(); } static void nwrap_endhostent(void) { nwrap_files_endhostent(); } #ifdef HAVE_SOLARIS_ENDHOSTENT int endhostent(void) { if (!nss_wrapper_hosts_enabled()) { libc_endhostent(); return 0; } nwrap_endhostent(); return 0; } #else /* HAVE_SOLARIS_ENDHOSTENT */ void endhostent(void) { if (!nss_wrapper_hosts_enabled()) { libc_endhostent(); return; } nwrap_endhostent(); } #endif /* HAVE_SOLARIS_ENDHOSTENT */ #ifdef BSD /* BSD implementation stores data in thread local storage but GLIBC does not */ static __thread struct hostent user_he; static __thread struct nwrap_vector user_addrlist; #else static struct hostent user_he; static struct nwrap_vector user_addrlist; #endif /* BSD */ static struct hostent *nwrap_gethostbyname(const char *name) { if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) { return NULL; } return &user_he; } struct hostent *gethostbyname(const char *name) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname(name); } return nwrap_gethostbyname(name); } /* This is a GNU extension - Also can be found on BSD systems */ #ifdef HAVE_GETHOSTBYNAME2 #ifdef BSD /* BSD implementation stores data in thread local storage but GLIBC not */ static __thread struct hostent user_he2; static __thread struct nwrap_vector user_addrlist2; #else static struct hostent user_he2; static struct nwrap_vector user_addrlist2; #endif /* BSD */ static struct hostent *nwrap_gethostbyname2(const char *name, int af) { if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) { return NULL; } return &user_he2; } struct hostent *gethostbyname2(const char *name, int af) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname2(name, af); } return nwrap_gethostbyname2(name, af); } #endif static struct hostent *nwrap_gethostbyaddr(const void *addr, socklen_t len, int type) { return nwrap_files_gethostbyaddr(addr, len, type); } struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyaddr(addr, len, type); } return nwrap_gethostbyaddr(addr, len, type); } static const struct addrinfo default_hints = { .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED, .ai_family = AF_UNSPEC, .ai_socktype = 0, .ai_protocol = 0, .ai_addrlen = 0, .ai_addr = NULL, .ai_canonname = NULL, .ai_next = NULL }; static int nwrap_convert_he_ai(const struct hostent *he, unsigned short port, const struct addrinfo *hints, struct addrinfo **pai, bool skip_canonname) { struct addrinfo *ai; socklen_t socklen; if (he == NULL) { return EAI_MEMORY; } switch (he->h_addrtype) { case AF_INET: socklen = sizeof(struct sockaddr_in); break; #ifdef HAVE_IPV6 case AF_INET6: socklen = sizeof(struct sockaddr_in6); break; #endif default: return EAI_FAMILY; } ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen); if (ai == NULL) { return EAI_MEMORY; } ai->ai_flags = hints->ai_flags; ai->ai_family = he->h_addrtype; ai->ai_socktype = hints->ai_socktype; ai->ai_protocol = hints->ai_protocol; ai->ai_canonname = NULL; if (ai->ai_socktype == 0) { ai->ai_socktype = SOCK_DGRAM; } if (ai->ai_protocol == 0) { if (ai->ai_socktype == SOCK_DGRAM) { ai->ai_protocol = IPPROTO_UDP; } else if (ai->ai_socktype == SOCK_STREAM) { ai->ai_protocol = IPPROTO_TCP; } } ai->ai_addrlen = socklen; ai->ai_addr = (void *)(ai + 1); #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN ai->ai_addr->sa_len = socklen; #endif ai->ai_addr->sa_family = he->h_addrtype; switch (he->h_addrtype) { case AF_INET: { struct sockaddr_in *sinp = (struct sockaddr_in *) ai->ai_addr; memset(sinp, 0, sizeof(struct sockaddr_in)); sinp->sin_port = htons(port); sinp->sin_family = AF_INET; memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length); } break; #ifdef HAVE_IPV6 case AF_INET6: { struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) ai->ai_addr; memset(sin6p, 0, sizeof(struct sockaddr_in6)); sin6p->sin6_port = htons(port); sin6p->sin6_family = AF_INET6; memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length); } break; #endif } ai->ai_next = NULL; if (he->h_name && !skip_canonname) { ai->ai_canonname = strdup(he->h_name); if (ai->ai_canonname == NULL) { freeaddrinfo(ai); return EAI_MEMORY; } } *pai = ai; return 0; } static int nwrap_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *ai = NULL; unsigned short port = 0; struct { int family; union { struct in_addr v4; #ifdef HAVE_IPV6 struct in6_addr v6; } in; #endif } addr = { .family = AF_UNSPEC, }; int rc; if (node == NULL && service == NULL) { return EAI_NONAME; } if (hints == NULL) { hints = &default_hints; } /* EAI_BADFLAGS hints.ai_flags contains invalid flags; or, hints.ai_flags included AI_CANONNAME and name was NULL. */ if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) { return EAI_BADFLAGS; } /* If no node has been specified, let glibc deal with it */ if (node == NULL) { int ret; struct addrinfo *p = NULL; ret = libc_getaddrinfo(node, service, hints, &p); if (ret == 0) { *res = p; } return ret; } if (service != NULL && service[0] != '\0') { const char *proto = NULL; struct servent *s; char *end_ptr; long sl; errno = 0; sl = strtol(service, &end_ptr, 10); if (*end_ptr == '\0') { port = sl; goto valid_port; } else if (hints->ai_flags & AI_NUMERICSERV) { return EAI_NONAME; } if (hints->ai_protocol != 0) { struct protoent *pent; pent = getprotobynumber(hints->ai_protocol); if (pent != NULL) { proto = pent->p_name; } } s = getservbyname(service, proto); if (s == NULL) { return EAI_NONAME; } port = ntohs(s->s_port); } valid_port: rc = inet_pton(AF_INET, node, &addr.in.v4); if (rc == 1) { addr.family = AF_INET; } #ifdef HAVE_IPV6 if (addr.family == AF_UNSPEC) { rc = inet_pton(AF_INET6, node, &addr.in.v6); if (rc == 1) { addr.family = AF_INET6; } } #endif if (addr.family == AF_UNSPEC) { if (hints->ai_flags & AI_NUMERICHOST) { return EAI_NONAME; } } else if ((hints->ai_family != AF_UNSPEC) && (hints->ai_family != addr.family)) { return EAI_ADDRFAMILY; } rc = nwrap_files_getaddrinfo(node, port, hints, &ai); if (rc != 0) { int ret; struct addrinfo *p = NULL; ret = libc_getaddrinfo(node, service, hints, &p); if (ret == 0) { /* * nwrap_files_getaddrinfo failed, but libc was * successful -- use the result from libc. */ *res = p; return 0; } return rc; } /* * If the socktype was not specified, duplicate * each ai returned, so that we have variants for * both UDP and TCP. */ if (hints->ai_socktype == 0) { struct addrinfo *ai_cur; /* freeaddrinfo() frees ai_canonname and ai so allocate them */ for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) { struct addrinfo *ai_new; /* duplicate the current entry */ ai_new = malloc(sizeof(struct addrinfo)); if (ai_new == NULL) { freeaddrinfo(ai); return EAI_MEMORY; } memcpy(ai_new, ai_cur, sizeof(struct addrinfo)); ai_new->ai_next = NULL; /* We need a deep copy or freeaddrinfo() will blow up */ if (ai_cur->ai_canonname != NULL) { ai_new->ai_canonname = strdup(ai_cur->ai_canonname); } if (ai_cur->ai_socktype == SOCK_DGRAM) { ai_new->ai_socktype = SOCK_STREAM; } else if (ai_cur->ai_socktype == SOCK_STREAM) { ai_new->ai_socktype = SOCK_DGRAM; } if (ai_cur->ai_protocol == IPPROTO_TCP) { ai_new->ai_protocol = IPPROTO_UDP; } else if (ai_cur->ai_protocol == IPPROTO_UDP) { ai_new->ai_protocol = IPPROTO_TCP; } /* now insert the new entry */ ai_new->ai_next = ai_cur->ai_next; ai_cur->ai_next = ai_new; /* and move on (don't duplicate the new entry) */ ai_cur = ai_new; } } *res = ai; return 0; } int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { if (!nss_wrapper_hosts_enabled()) { return libc_getaddrinfo(node, service, hints, res); } return nwrap_getaddrinfo(node, service, hints, res); } static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct hostent *he; struct servent *service; const char *proto; const void *addr; socklen_t addrlen; uint16_t port; sa_family_t type; if (sa == NULL || salen < sizeof(sa_family_t)) { return EAI_FAMILY; } if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) { return EAI_NONAME; } type = sa->sa_family; switch (type) { case AF_INET: if (salen < sizeof(struct sockaddr_in)) return EAI_FAMILY; addr = &((const struct sockaddr_in *)sa)->sin_addr; addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr); port = ntohs(((const struct sockaddr_in *)sa)->sin_port); break; #ifdef HAVE_IPV6 case AF_INET6: if (salen < sizeof(struct sockaddr_in6)) return EAI_FAMILY; addr = &((const struct sockaddr_in6 *)sa)->sin6_addr; addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr); port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port); break; #endif default: return EAI_FAMILY; } if (host != NULL) { he = NULL; if ((flags & NI_NUMERICHOST) == 0) { he = nwrap_files_gethostbyaddr(addr, addrlen, type); if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL)) return EAI_NONAME; } if (he != NULL && he->h_name != NULL) { if (strlen(he->h_name) >= hostlen) return EAI_OVERFLOW; snprintf(host, hostlen, "%s", he->h_name); if (flags & NI_NOFQDN) host[strcspn(host, ".")] = '\0'; } else { if (inet_ntop(type, addr, host, hostlen) == NULL) return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL; } } if (serv != NULL) { service = NULL; if ((flags & NI_NUMERICSERV) == 0) { proto = (flags & NI_DGRAM) ? "udp" : "tcp"; service = getservbyport(htons(port), proto); } if (service != NULL) { if (strlen(service->s_name) >= servlen) return EAI_OVERFLOW; snprintf(serv, servlen, "%s", service->s_name); } else { if (snprintf(serv, servlen, "%u", port) >= (int) servlen) return EAI_OVERFLOW; } } return 0; } #ifdef HAVE_LINUX_GETNAMEINFO int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED) int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, unsigned int flags) #else int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) #endif { if (!nss_wrapper_hosts_enabled()) { return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } static int nwrap_gethostname(char *name, size_t len) { const char *hostname = getenv("NSS_WRAPPER_HOSTNAME"); if (strlen(hostname) >= len) { errno = ENAMETOOLONG; return -1; } snprintf(name, len, "%s", hostname); return 0; } #ifdef HAVE_SOLARIS_GETHOSTNAME int gethostname(char *name, int len) #else /* HAVE_SOLARIS_GETHOSTNAME */ int gethostname(char *name, size_t len) #endif /* HAVE_SOLARIS_GETHOSTNAME */ { if (!nwrap_hostname_enabled()) { return libc_gethostname(name, len); } return nwrap_gethostname(name, len); } /**************************** * DESTRUCTOR ***************************/ /* * This function is called when the library is unloaded and makes sure that * sockets get closed and the unix file for the socket are unlinked. */ void nwrap_destructor(void) { int i; NWRAP_LOCK_ALL; if (nwrap_main_global != NULL) { struct nwrap_main *m = nwrap_main_global; /* libc */ SAFE_FREE(m->libc->fns); if (m->libc->handle != NULL) { dlclose(m->libc->handle); } if (m->libc->nsl_handle != NULL) { dlclose(m->libc->nsl_handle); } if (m->libc->sock_handle != NULL) { dlclose(m->libc->sock_handle); } SAFE_FREE(m->libc); /* backends */ for (i = 0; i < m->num_backends; i++) { struct nwrap_backend *b = &(m->backends[i]); if (b->so_handle != NULL) { dlclose(b->so_handle); } SAFE_FREE(b->fns); } SAFE_FREE(m->backends); } if (nwrap_pw_global.cache != NULL) { struct nwrap_cache *c = nwrap_pw_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } SAFE_FREE(nwrap_pw_global.list); nwrap_pw_global.num = 0; } if (nwrap_gr_global.cache != NULL) { struct nwrap_cache *c = nwrap_gr_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } SAFE_FREE(nwrap_gr_global.list); nwrap_pw_global.num = 0; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) if (nwrap_sp_global.cache != NULL) { struct nwrap_cache *c = nwrap_sp_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } nwrap_sp_global.num = 0; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ if (nwrap_he_global.cache != NULL) { struct nwrap_cache *c = nwrap_he_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } nwrap_he_global.num = 0; } free(user_addrlist.items); #ifdef HAVE_GETHOSTBYNAME2 free(user_addrlist2.items); #endif hdestroy(); NWRAP_UNLOCK_ALL; } nss_wrapper-1.1.3/tests/000755 001750 000144 00000000000 12672772135 015215 5ustar00asnusers000000 000000 nss_wrapper-1.1.3/tests/group.in000644 001750 000144 00000000103 12247646107 016670 0ustar00asnusers000000 000000 users:x:1000: nobody:x:65533: nogroup:x:65534:nobody root:x:65532: nss_wrapper-1.1.3/tests/nss_nwrap.c000644 001750 000144 00000006536 12254775552 017407 0ustar00asnusers000000 000000 #include "config.h" #include #include #if defined(HAVE_NSS_H) /* Linux and BSD */ #include typedef enum nss_status NSS_STATUS; #elif defined(HAVE_NSS_COMMON_H) /* Solaris */ #include #include #include typedef nss_status_t NSS_STATUS; # define NSS_STATUS_SUCCESS NSS_SUCCESS # define NSS_STATUS_NOTFOUND NSS_NOTFOUND # define NSS_STATUS_UNAVAIL NSS_UNAVAIL # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN #else # error "No nsswitch support detected" #endif NSS_STATUS _nss_nwrap_setpwent(void); NSS_STATUS _nss_nwrap_endpwent(void); NSS_STATUS _nss_nwrap_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_getpwnam_r(const char *name, struct passwd *result, 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_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); NSS_STATUS _nss_nwrap_setpwent(void) { return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_endpwent(void) { return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { (void) result; (void) buffer; (void) buflen; (void) errnop; return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { (void) uid; (void) result; (void) buffer; (void) buflen; (void) errnop; return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwnam_r(const char *name, struct passwd *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_setgrent(void) { return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_endgrent(void) { return NSS_STATUS_UNAVAIL; } 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; } 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_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_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) { (void) user; (void) group; (void) start; (void) size; (void) groups; (void) limit; (void) errnop; return NSS_STATUS_UNAVAIL; } nss_wrapper-1.1.3/tests/passwd.in000644 001750 000144 00000000307 12620616655 017043 0ustar00asnusers000000 000000 bob:x:1000:1000:bob gecos:@HOMEDIR@:/bin/false alice:1001:1000:alice gecos:@HOMEDIR@:/bin/false nobody:x:65533:65534:bob gecos:@HOMEDIR@:/bin/false root:x:65534:65532:root gecos:@HOMEDIR@:/bin/false nss_wrapper-1.1.3/tests/shadow.in000644 001750 000144 00000000356 12620616655 017033 0ustar00asnusers000000 000000 alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/:1:0:99999:7::: bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/:2:0:99999:7::: nss_wrapper-1.1.3/tests/test_gethostent.c000644 001750 000144 00000002051 12620616655 020577 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_gethostent(void **state) { struct hostent *he; uint32_t i; (void)state; /* unused */ sethostent(0); for (he = gethostent(); he != NULL; he = gethostent()) { assert_non_null(he->h_addr_list); assert_non_null(he->h_aliases); for (i = 0; he->h_addr_list[i] != NULL; i++) { char buf[INET6_ADDRSTRLEN]; uint32_t j; const char *ip; ip = inet_ntop(he->h_addrtype, he->h_addr_list[i], buf, sizeof(buf)); printf("ip: %s\n", ip); for (j = 0; he->h_aliases[j] != NULL; j++) { printf("alias: %s\n", he->h_aliases[j]); } } } endhostent(); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_gethostent), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/test_getnameinfo.c000644 001750 000144 00000016565 12620616655 020726 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_getnameinfo(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(53); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "magrathea.galaxy.site"); assert_string_equal(serv, "domain"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(53); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); assert_string_equal(serv, "domain"); } static void test_nwrap_getnameinfo_numeric(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(53); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_NUMERICHOST; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "127.0.0.11"); assert_string_equal(serv, "domain"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(53); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); flags = NI_NUMERICSERV; rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); assert_string_equal(serv, "53"); } static void test_nwrap_getnameinfo_any(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "0.0.0.0", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "0.0.0.0"); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "::"); assert_string_equal(serv, "ssh"); } static void test_nwrap_getnameinfo_local(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "127.0.0.1"); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "::1"); assert_string_equal(serv, "ssh"); } static void test_nwrap_getnameinfo_null(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ rc = getnameinfo(NULL, 0, host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, EAI_FAMILY); /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), NULL, 0, serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), NULL, 0, flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), NULL, 0, NULL, 0, flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); } static void test_nwrap_getnameinfo_flags(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; int flags = 0; int rc; (void) state; /* unused */ /* NI_NAMEREQD */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_NAMEREQD; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), NULL, 0, NULL, 0, flags); assert_int_equal(rc, EAI_NONAME); /* NI_DGRAM */ sin.sin_family = AF_INET; sin.sin_port = htons(513); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_DGRAM; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "who"); /* STREAM (port 513) */ flags = 0; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "login"); /* NI_NOFQDN */ flags = NI_NOFQDN; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "magrathea"); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getnameinfo), cmocka_unit_test(test_nwrap_getnameinfo_numeric), cmocka_unit_test(test_nwrap_getnameinfo_any), cmocka_unit_test(test_nwrap_getnameinfo_local), cmocka_unit_test(test_nwrap_getnameinfo_null), cmocka_unit_test(test_nwrap_getnameinfo_flags), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/test_nwrap_disabled.c000644 001750 000144 00000003742 12620616655 021401 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_passwd_group(void **state) { struct passwd *pwd; struct group *grp; (void) state; /* unused */ pwd = getpwuid(getuid()); assert_non_null(pwd); pwd = getpwnam(pwd->pw_name); assert_non_null(pwd); grp = getgrgid(pwd->pw_gid); assert_non_null(grp); grp = getgrnam(grp->gr_name); assert_non_null(grp); } /* Test libnsl */ static void test_nwrap_hostent(void **state) { struct hostent *he; (void) state; /* unused */ sethostent(0); he = gethostent(); assert_non_null(he); endhostent(); } static void test_nwrap_gethostname(void **state) { char host[256] = {0}; int rc; (void) state; /* unused */ rc = gethostname(host, sizeof(host)); assert_int_equal(rc, 0); assert_true(strlen(host) > 1); } static void test_nwrap_getaddrinfo_local(void **state) { struct addrinfo hints; struct addrinfo *res; struct sockaddr_in *sinp; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; rc = getaddrinfo("127.0.0.1", NULL, &hints, &res); assert_int_equal(rc, 0); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_null(res->ai_canonname); sinp = (struct sockaddr_in *)res->ai_addr; assert_int_equal(ntohl(sinp->sin_addr.s_addr), INADDR_LOOPBACK); freeaddrinfo(res); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_passwd_group), cmocka_unit_test(test_nwrap_hostent), cmocka_unit_test(test_nwrap_gethostname), cmocka_unit_test(test_nwrap_getaddrinfo_local), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/test_nwrap_vector.c000644 001750 000144 00000007055 12620616655 021135 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include "../src/nss_wrapper.c" static void test_nwrap_vector_basic_add(void **state) { struct nwrap_vector v; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v); assert_non_null(v.items); nwrap_vector_add_item(&v, string); assert_null(v.items[1]); assert_int_equal(v.count, 1); assert_string_equal(v.items[0], string); assert_int_equal(v.capacity, DEFAULT_VECTOR_CAPACITY); assert_string_equal(v.items[0], "string!"); nwrap_vector_add_item(&v, string2); assert_null(v.items[2]); assert_int_equal(v.count, 2); assert_string_equal(v.items[0], string); assert_string_equal(v.items[1], string2); free(v.items); } static void test_nwrap_vector_merge_empty(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); assert_int_equal(v1.count, 0); nwrap_vector_init(&v2); assert_non_null(v2.items); assert_int_equal(v2.count, 0); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 0); assert_null(v1.items[0]); nwrap_vector_add_item(&v1, string); nwrap_vector_add_item(&v1, string2); assert_int_equal(v1.count, 2); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 2); assert_string_equal(v1.items[0], string); assert_string_equal(v1.items[1], string2); assert_null(v1.items[2]); nwrap_vector_merge(&v2, &v1); assert_int_equal(v2.count, 2); assert_string_equal(v2.items[0], string); assert_string_equal(v2.items[1], string2); assert_null(v2.items[2]); free(v1.items); free(v2.items); } static void test_nwrap_vector_merge(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); nwrap_vector_add_item(&v1, string); nwrap_vector_add_item(&v1, string2); assert_int_equal(v1.count, 2); nwrap_vector_init(&v2); assert_non_null(v2.items); nwrap_vector_add_item(&v2, string2); nwrap_vector_add_item(&v2, string); assert_int_equal(v2.count, 2); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 4); assert_string_equal(v1.items[0], string); assert_string_equal(v1.items[1], string2); assert_string_equal(v1.items[2], string2); assert_string_equal(v1.items[3], string); assert_null(v1.items[4]); free(v1.items); free(v2.items); } static void test_nwrap_vector_merge_max(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; int p; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); for (p = 0; p < 64; ++p) { nwrap_vector_add_item(&v1, string); } assert_int_equal(v1.count, 64); nwrap_vector_init(&v2); assert_non_null(v2.items); nwrap_vector_merge(&v2, &v1); assert_int_equal(v2.count, 64); for (p = 0; p < 64; ++p) { assert_string_equal(v2.items[p], string); } nwrap_vector_add_item(&v2, string2); assert_string_equal(v2.items[64], string2); assert_int_equal(v2.count, 65); assert_null(v2.items[65]); free(v1.items); free(v2.items); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_vector_basic_add), cmocka_unit_test(test_nwrap_vector_merge_empty), cmocka_unit_test(test_nwrap_vector_merge), cmocka_unit_test(test_nwrap_vector_merge_max), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/test_shadow.c000644 001750 000144 00000002457 12620616655 017712 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include static void test_nwrap_getspent(void **state) { struct spwd *sp; uint32_t i; (void)state; /* unused */ setspent(); for (sp = getspent(), i = 0; sp != NULL; sp = getspent(), i++) { if (i == 0) { assert_string_equal(sp->sp_namp, "alice"); } else { assert_string_equal(sp->sp_namp, "bob"); } } endspent(); } static void test_nwrap_getspnam(void **state) { char *encrypted_password; struct spwd *sp; (void)state; /* unused */ sp = getspnam("alice"); assert_non_null(sp); assert_string_equal(sp->sp_namp, "alice"); encrypted_password = crypt("secret", sp->sp_pwdp); assert_non_null(encrypted_password); assert_string_equal(encrypted_password, sp->sp_pwdp); sp = getspnam("bob"); assert_non_null(sp); assert_string_equal(sp->sp_namp, "bob"); encrypted_password = crypt("secret", sp->sp_pwdp); assert_non_null(encrypted_password); assert_string_equal(encrypted_password, sp->sp_pwdp); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getspent), cmocka_unit_test(test_nwrap_getspnam), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/test_gethostby_name_addr.c000644 001750 000144 00000015727 12622316322 022421 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NSS_WRAPPER_HOSTNAME_ENV "NSS_WRAPPER_HOSTNAME" static void test_nwrap_gethostname(void **state) { const char *hostname = "milliways"; char sys_host[256] = {0}; char host[16] = {0}; int rc; (void) state; /* unused */ rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, hostname, 1); assert_int_equal(rc, 0); rc = gethostname(host, sizeof(host)); assert_int_equal(rc, 0); assert_string_equal(host, hostname); rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, "this_hostname_is_too_long", 1); assert_int_equal(rc, 0); rc = gethostname(host, sizeof(host)); assert_int_equal(rc, -1); assert_int_equal(errno, ENAMETOOLONG); unsetenv(NSS_WRAPPER_HOSTNAME_ENV); rc = gethostname(sys_host, sizeof(sys_host)); assert_int_equal(rc, 0); } static void *thread_test_gethostbyname(void *u) { struct hostent *he; (void) u; /* unused */ he = gethostbyname("magrathea"); assert_non_null(he); assert_non_null(he->h_name); assert_string_equal(he->h_name, "magrathea.galaxy.site"); pthread_exit(NULL); } static void test_nwrap_gethostbyname_thread(void **state) { struct hostent *he; pthread_t th; (void) state; /* unused */ he = gethostbyname("maximegalon.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_string_equal(he->h_name, "maximegalon.galaxy.site"); pthread_create(&th, NULL, &thread_test_gethostbyname, NULL); pthread_join(th, NULL); assert_non_null(he); assert_non_null(he->h_name); #ifdef BSD /* * On *BSD (and Mac OS X) systems, * data is stored in thread local storage. */ assert_string_equal(he->h_name, "maximegalon.galaxy.site"); #else /* * Glibc doesn't store data in thread local storage, so calling * gethostbyname from a thread overwrites the parent thread's data. */ assert_string_equal(he->h_name, "magrathea.galaxy.site"); #endif } static void test_nwrap_gethostbyname(void **state) { char ip[INET_ADDRSTRLEN]; struct hostent *he; const char *a; (void) state; /* unused */ he = gethostbyname("magrathea.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.11"); } static void test_nwrap_gethostbyname_multiple(void **state) { struct hostent *he; char **list; /* For inet_ntop call */ char buf[4096]; const char *result; char *p = buf; /* List of ips in hosts file - order matters */ const char *const result_ips[] = { "127.0.0.11", "127.0.0.12", NULL }; const char *actual_ip = result_ips[0]; unsigned int ac; (void) state; /* unused */ he = gethostbyname("magrathea.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); list = he->h_addr_list; for (ac = 0; *list != NULL; ++ac, ++list) { actual_ip = result_ips[ac]; /* When test fails here more records are returned */ assert_non_null(actual_ip); result = inet_ntop(AF_INET, *list, p, 4096); assert_non_null(p); assert_string_equal(actual_ip, result); } } #ifdef HAVE_GETHOSTBYNAME2 static void test_nwrap_gethostbyname2(void **state) { char ip[INET6_ADDRSTRLEN]; struct hostent *he; const char *a; (void) state; /* unused */ he = gethostbyname2("magrathea.galaxy.site", AF_INET6); assert_non_null(he); he = gethostbyname2("magrathea.galaxy.site", AF_INET); assert_non_null(he); /* Check ipv6 he */ he = gethostbyname2("krikkit.galaxy.site", AF_INET6); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "krikkit.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET6); a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "::14"); /* Check ipv4 he */ he = gethostbyname2("krikkit.galaxy.site", AF_INET); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "krikkit.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.14"); } #endif /* HAVE_GETHOSTBYNAME2 */ static void test_nwrap_gethostbyaddr(void **state) { struct hostent *he; struct in_addr in; int rc; (void) state; /* unused */ rc = inet_aton("127.0.0.11", &in); assert_int_equal(rc, 1); he = gethostbyaddr(&in, sizeof(struct in_addr), AF_INET); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); assert_memory_equal(&in, he->h_addr_list[0], he->h_length); } #ifdef HAVE_GETHOSTBYNAME_R static void test_nwrap_gethostbyname_r(void **state) { char buf[1024] = {0}; char ip[INET_ADDRSTRLEN]; struct hostent hb, *he; const char *a; int herr = 0; int rc; (void) state; /* unused */ rc = gethostbyname_r("magrathea.galaxy.site", &hb, buf, sizeof(buf), &he, &herr); assert_int_equal(rc, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.11"); } #endif #ifdef HAVE_GETHOSTBYADDR_R static void test_nwrap_gethostbyaddr_r(void **state) { char buf[1024] = {0}; struct hostent hb, *he; struct in_addr in; int herr = 0; int rc; (void) state; /* unused */ rc = inet_aton("127.0.0.11", &in); assert_int_equal(rc, 1); rc = gethostbyaddr_r(&in, sizeof(struct in_addr), AF_INET, &hb, buf, sizeof(buf), &he, &herr); assert_int_equal(rc, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); assert_memory_equal(&in, he->h_addr_list[0], he->h_length); } #endif int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_gethostname), cmocka_unit_test(test_nwrap_gethostbyname), cmocka_unit_test(test_nwrap_gethostbyname_thread), #ifdef HAVE_GETHOSTBYNAME2 cmocka_unit_test(test_nwrap_gethostbyname2), #endif cmocka_unit_test(test_nwrap_gethostbyaddr), #ifdef HAVE_GETHOSTBYNAME_R cmocka_unit_test(test_nwrap_gethostbyname_r), #endif #ifdef HAVE_GETHOSTBYADDR_R cmocka_unit_test(test_nwrap_gethostbyaddr_r), #endif cmocka_unit_test(test_nwrap_gethostbyname_multiple), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/CMakeLists.txt000644 001750 000144 00000004215 12623564401 017746 0ustar00asnusers000000 000000 project(tests C) include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMOCKA_INCLUDE_DIR} ) set(TESTSUITE_LIBRARIES ${NWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY}) add_library(nss_nwrap SHARED nss_nwrap.c) set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}) configure_file(passwd.in ${CMAKE_CURRENT_BINARY_DIR}/passwd @ONLY) configure_file(group.in ${CMAKE_CURRENT_BINARY_DIR}/group @ONLY) configure_file(hosts.in ${CMAKE_CURRENT_BINARY_DIR}/hosts @ONLY) configure_file(shadow.in ${CMAKE_CURRENT_BINARY_DIR}/shadow @ONLY) set(TEST_ENVIRONMENT LD_PRELOAD=${NSS_WRAPPER_LOCATION}) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_PASSWD=${CMAKE_CURRENT_BINARY_DIR}/passwd) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_GROUP=${CMAKE_CURRENT_BINARY_DIR}/group) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_SHADOW=${CMAKE_CURRENT_BINARY_DIR}/shadow) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_HOSTS=${CMAKE_CURRENT_BINARY_DIR}/hosts) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_MODULE_SO_PATH=${CMAKE_CURRENT_BINARY_DIR}/libnss_nwrap.so) list(APPEND TEST_ENVIRONMENT NSS_WRAPPER_MODULE_FN_PREFIX=nwrap) set(NWRAP_TESTS testsuite test_nwrap_vector test_getaddrinfo test_getnameinfo test_gethostby_name_addr test_gethostent) if (HAVE_SHADOW_H) list(APPEND NWRAP_TESTS test_shadow) endif (HAVE_SHADOW_H) foreach(_NWRAP_TEST ${NWRAP_TESTS}) add_cmocka_test(${_NWRAP_TEST} ${_NWRAP_TEST}.c ${TESTSUITE_LIBRARIES}) set_property( TEST ${_NWRAP_TEST} PROPERTY ENVIRONMENT ${TEST_ENVIRONMENT}) endforeach() if (HAVE_SHADOW_H) # This is needed to check the hash in tests/shadow.in target_link_libraries(test_shadow crypt) endif (HAVE_SHADOW_H) target_link_libraries(test_nwrap_vector ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(test_gethostby_name_addr ${CMAKE_THREAD_LIBS_INIT}) if (BSD) add_definitions(-DBSD) endif (BSD) # Test nwrap without wrapping so the libc functions are called add_cmocka_test(test_nwrap_disabled test_nwrap_disabled.c ${TESTSUITE_LIBRARIES}) set_property( TEST test_nwrap_disabled PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/src/libnss_wrapper.so) nss_wrapper-1.1.3/tests/valgrind.supp000644 001750 000144 00000001026 12624540402 017716 0ustar00asnusers000000 000000 ### GLIBC { glibc_dlopen_worker_alloc Memcheck:Leak fun:*alloc ... fun:dl_open_worker fun:_dl_catch_error fun:_dl_open fun:dlopen_doit fun:_dl_catch_error fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 } { glibc_dlopen_alloc Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 } { glibc_dlclose_alloc Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlclose } { glibc___sha512_crypt_alloc Memcheck:Leak fun:malloc fun:realloc fun:__sha512_crypt } nss_wrapper-1.1.3/tests/hosts.in000644 001750 000144 00000013004 12634462252 016675 0ustar00asnusers000000 000000 127.0.0.11 magrathea.galaxy.site magrathea 127.0.0.12 magrathea.galaxy.site magrathea ::29a magrathea.galaxy.site magrathea 127.0.0.12 maximegalon.galaxy.site ::13 beteigeuze.galaxy.site beteigeuze mail 127.0.0.14 krikkit.galaxy.site ::14 krikkit.galaxy.site 127.1.1.1 pumpkin.bunny.net pumpkin.bunny.net 127.0.0.66 pumpkin.bunny.net 2666::22 pumpkin.bunny.net DEAD:BEEF:1:2:3::4 pumpkin.bunny.net B00B:5::4 pumpkin.bunny.net 127.0.0.21 localdc.samba.example.com samba.example.com localdc fd00:0000:0000:0000:0000:0000:5357:5f15 localdc.samba.example.com samba.example.com localdc 127.0.0.3 localnt4dc2.samba.example.com localnt4dc2 fd00:0000:0000:0000:0000:0000:5357:5f03 localnt4dc2.samba.example.com localnt4dc2 127.0.0.5 localshare4.samba.example.com localshare4 fd00:0000:0000:0000:0000:0000:5357:5f05 localshare4.samba.example.com localshare4 127.0.0.4 localnt4member3.samba.example.com localnt4member3 fd00:0000:0000:0000:0000:0000:5357:5f04 localnt4member3.samba.example.com localnt4member3 127.0.0.29 localadmember.samba.example.com localadmember fd00:0000:0000:0000:0000:0000:5357:5f1d localadmember.samba.example.com localadmember 127.0.0.23 s4member.samba.example.com s4member fd00:0000:0000:0000:0000:0000:5357:5f17 s4member.samba.example.com s4member 127.0.0.7 localktest6.samba.example.com localktest6 fd00:0000:0000:0000:0000:0000:5357:5f07 localktest6.samba.example.com localktest6 127.0.0.8 maptoguest.samba.example.com maptoguest fd00:0000:0000:0000:0000:0000:5357:5f08 maptoguest.samba.example.com maptoguest 127.0.0.35 fileserver.samba.example.com fileserver fd00:0000:0000:0000:0000:0000:5357:5f23 fileserver.samba.example.com fileserver 127.0.0.30 addc.addc.samba.example.com addc fd00:0000:0000:0000:0000:0000:5357:5f1e addc.addc.samba.example.com addc 127.0.0.9 localnt4dc9.samba.example.com localnt4dc9 fd00:0000:0000:0000:0000:0000:5357:5f09 localnt4dc9.samba.example.com localnt4dc9 127.0.0.34 rfc2307member.samba.example.com rfc2307member fd00:0000:0000:0000:0000:0000:5357:5f22 rfc2307member.samba.example.com rfc2307member 127.0.0.25 dc5.samba2000.example.com dc5 fd00:0000:0000:0000:0000:0000:5357:5f19 dc5.samba2000.example.com dc5 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 nss_wrapper-1.1.3/tests/test_getaddrinfo.c000644 001750 000144 00000042757 12650151464 020715 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_getaddrinfo(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in *sinp; struct sockaddr_in6 *sin6p; char ip6[INET6_ADDRSTRLEN]; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); assert_int_equal(res->ai_family, AF_INET); sinp = (struct sockaddr_in *)res->ai_addr; assert_int_equal(sinp->sin_family, AF_INET); ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); res = NULL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("::13", NULL, &hints, &res); assert_non_null(res); assert_int_equal(rc, 0); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "beteigeuze.galaxy.site"); assert_int_equal(res->ai_family, AF_INET6); sin6p = (struct sockaddr_in6 *)res->ai_addr; assert_int_equal(sin6p->sin6_family, AF_INET6); inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::13"); freeaddrinfo(res); } /* * The purpose of this test is to verify that reloading of the hosts * file (triggered by a timestamp change) correctly frees and re-creates * the internal data structures, so we do not end up using invalid memory. */ static void test_nwrap_getaddrinfo_reload(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; const char *env; char touch_cmd[1024]; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; env = getenv("NSS_WRAPPER_HOSTS"); assert_non_null(env); snprintf(touch_cmd, sizeof(touch_cmd), "touch %s", env); rc = system(touch_cmd); assert_return_code(rc, errno); rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_samba(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_STREAM; /* Stream socket */ hints.ai_flags = 0; /* For wildcard IP address */ hints.ai_protocol = IPPROTO_TCP; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.21", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("samba.example.com", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("localdc", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("localdc.samba.example.com", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("fd00:0000:0000:0000:0000:0000:5357:5f15", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_any(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in *sinp; struct sockaddr_in6 *sin6p; char ip6[INET6_ADDRSTRLEN]; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; rc = getaddrinfo("0.0.0.0", "389", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_null(res->ai_canonname); sinp = (struct sockaddr_in *)res->ai_addr; assert_int_equal(389, htons(sinp->sin_port)); ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "0.0.0.0"); freeaddrinfo(res); res = NULL; /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; rc = getaddrinfo("::", "389", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET6); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_null(res->ai_canonname); sin6p = (struct sockaddr_in6 *)res->ai_addr; assert_int_equal(389, htons(sin6p->sin6_port)); inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_local(void **state) { struct addrinfo hints; struct addrinfo *res; struct sockaddr_in *sinp; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("127.0.0.1", NULL, &hints, &res); assert_int_equal(rc, 0); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_null(res->ai_canonname); sinp = (struct sockaddr_in *)res->ai_addr; ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "127.0.0.1"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_name(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in *sinp; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("maximegalon.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "maximegalon.galaxy.site"); sinp = (struct sockaddr_in *)res->ai_addr; ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "127.0.0.12"); freeaddrinfo(res); res = NULL; /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("MAGRATHEA", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); sinp = (struct sockaddr_in *)res->ai_addr; ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_service(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in *sinp; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("magrathea", "wurst", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* Check ldap port */ rc = getaddrinfo("magrathea", "ldap", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); assert_non_null(res->ai_addr); sinp = (struct sockaddr_in *)res->ai_addr; ip = inet_ntoa(sinp->sin_addr); assert_string_equal(ip, "127.0.0.11"); assert_int_equal(ntohs(sinp->sin_port), 389); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_null(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in6 *sin6p; char ip6[INET6_ADDRSTRLEN]; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 17; hints.ai_flags = 0; rc = getaddrinfo(NULL, NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); /* Check dns service */ rc = getaddrinfo(NULL, "domain", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_null(res->ai_canonname); assert_int_equal(res->ai_family, AF_INET6); assert_int_equal(res->ai_socktype, SOCK_DGRAM); assert_non_null(res->ai_addr); sin6p = (struct sockaddr_in6 *)res->ai_addr; inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::1"); freeaddrinfo(res); res = NULL; /* Check dns service */ rc = getaddrinfo("magrathea", "domain", NULL, &res); assert_non_null(res); assert_int_equal(rc, 0); assert_non_null(res->ai_canonname); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_dot(void **state) { struct addrinfo hints = { .ai_family = AF_INET, }; struct addrinfo *res = NULL; struct sockaddr_in *sinp; char ip[INET_ADDRSTRLEN]; int rc; (void) state; /* unused */ /* Check with a dot at the end */ rc = getaddrinfo("magrathea.galaxy.site.", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_next); assert_int_equal(res->ai_family, AF_INET); sinp = (struct sockaddr_in *)res->ai_addr; assert_int_equal(sinp->sin_family, AF_INET); inet_ntop(AF_INET, (void *)&sinp->sin_addr, ip, sizeof(ip)); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_ipv6(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; struct sockaddr_in6 *sin6p; char ip6[INET6_ADDRSTRLEN]; int rc; (void) state; /* unused */ /* * krikkit.galaxy has an IPv4 and IPv6 address, this should only * return the IPv6 address. */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; rc = getaddrinfo("krikkit.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_next); assert_int_equal(res->ai_family, AF_INET6); sin6p = (struct sockaddr_in6 *)res->ai_addr; assert_int_equal(sin6p->sin6_family, AF_INET6); inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::14"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_multiple_mixed(void **state) { struct addrinfo *res, *res_head; struct addrinfo hints; unsigned int ipv6_count = 0; unsigned int ipv4_count = 0; int rc; int p; struct sockaddr_in *r_addr; struct sockaddr_in6 *r_addr6; const char *result = NULL; const char *value = NULL; /* For inet_ntop call */ char buf[4096]; /* 2 - ipv4 and 3 ipv6 addresses */ const char *ipvX_results[] = {"127.1.1.1", "127.0.0.66", "2666::22", "B00B:5::4", "DEAD:BEEF:1:2:3::4", NULL}; (void) state; /* unused */ memset(&hints, '\0', sizeof(struct addrinfo)); hints.ai_protocol = IPPROTO_TCP; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo("pumpkin.bunny.net", NULL, &hints, &res_head); assert_return_code(rc, 0); assert_non_null(res_head); for (res = res_head; res != NULL; res = res->ai_next) { if (res->ai_family == AF_INET) { r_addr = (struct sockaddr_in *) res->ai_addr; assert_non_null(r_addr); ++ipv4_count; result = inet_ntop(AF_INET, &r_addr->sin_addr, buf, 4096); } else if (res->ai_family == AF_INET6) { r_addr6 = (struct sockaddr_in6 *) res->ai_addr; assert_non_null(r_addr6); ++ipv6_count; result = inet_ntop(AF_INET6, &r_addr6->sin6_addr, buf, 4096); } else { /* Unknown family type */ assert_int_equal(1,0); } /* Important part */ assert_non_null(result); /* This could be part of cmocka library */ for (value = ipvX_results[0], p = 0; value != NULL; value = ipvX_results[++p]) { if (strcasecmp(value, result) == 0) { break; } } assert_non_null(value); } assert_int_equal(ipv6_count, 3); assert_int_equal(ipv4_count, 2); freeaddrinfo(res_head); } static void test_nwrap_getaddrinfo_flags_ai_numericserv(void **state) { struct addrinfo hints; struct addrinfo *res; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; /* * Calls with NULL name are handled by libc, * even if nss_wrapper is enabled */ rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo(NULL, "80", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); res = NULL; /* Crippled input */ rc = getaddrinfo(NULL, "80a1", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* * Calls with non-NULL name are handled by nwrap */ rc = getaddrinfo("magrathea.galaxy.site", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("magrathea.galaxy.site", "80", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); res = NULL; /* Crippled input */ rc = getaddrinfo("magrathea.galaxy.site", "80a1", &hints, &res); assert_int_equal(rc, EAI_NONAME); } static void test_nwrap_getaddrinfo_flags_ai_numerichost(void **state) { struct addrinfo hints; struct addrinfo *res; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; /* IPv4 or IPv6 */ hints.ai_family = AF_UNSPEC; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("::1", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* IPv4 */ hints.ai_family = AF_INET; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("::1", NULL, &hints, &res); #ifdef EAI_ADDRFAMILY assert_int_equal(rc, EAI_ADDRFAMILY); #else assert_int_equal(rc, EAI_FAMILY); #endif rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* IPv6 */ hints.ai_family = AF_INET6; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); #ifdef EAI_ADDRFAMILY assert_int_equal(rc, EAI_ADDRFAMILY); #else assert_int_equal(rc, EAI_FAMILY); #endif rc = getaddrinfo("::1", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getaddrinfo), cmocka_unit_test(test_nwrap_getaddrinfo_reload), cmocka_unit_test(test_nwrap_getaddrinfo_any), cmocka_unit_test(test_nwrap_getaddrinfo_local), cmocka_unit_test(test_nwrap_getaddrinfo_name), cmocka_unit_test(test_nwrap_getaddrinfo_service), cmocka_unit_test(test_nwrap_getaddrinfo_null), cmocka_unit_test(test_nwrap_getaddrinfo_dot), cmocka_unit_test(test_nwrap_getaddrinfo_ipv6), cmocka_unit_test(test_nwrap_getaddrinfo_multiple_mixed), cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numericserv), cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numerichost), cmocka_unit_test(test_nwrap_getaddrinfo_samba), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/tests/testsuite.c000644 001750 000144 00000046413 12672602321 017407 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include /* * 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 * Solaris */ #ifndef _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS #endif #include #include #include #include #include #include #ifdef NDEBUG #define DEBUG(...) #else #define DEBUG(...) printf(__VA_ARGS__) #endif #ifndef SAFE_FREE #define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) #endif static void assert_passwd_equal(const struct passwd *p1, const struct passwd *p2) { assert_string_equal(p1->pw_name, p2->pw_name); assert_string_equal(p1->pw_passwd, p2->pw_passwd); assert_int_equal(p1->pw_uid, p2->pw_uid); assert_int_equal(p1->pw_gid, p2->pw_gid); assert_string_equal(p1->pw_gecos, p2->pw_gecos); assert_string_equal(p1->pw_dir, p2->pw_dir); assert_string_equal(p1->pw_shell, p2->pw_shell); } static void assert_group_equal(const struct group *g1, const struct group *g2) { int i; assert_string_equal(g1->gr_name, g2->gr_name); assert_string_equal(g1->gr_passwd, g2->gr_passwd); assert_int_equal(g1->gr_gid, g2->gr_gid); assert_false(g1->gr_mem != NULL && g2->gr_mem == NULL); assert_false(g1->gr_mem == NULL && g2->gr_mem != NULL); if (g1->gr_mem == NULL && g2->gr_mem == NULL) { return; } for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) { assert_string_equal(g1->gr_mem[i], g2->gr_mem[i]); } } static bool copy_passwd(const struct passwd *pwd, struct passwd *p) { p->pw_name = strdup(pwd->pw_name); p->pw_passwd = strdup(pwd->pw_passwd); p->pw_uid = pwd->pw_uid; p->pw_gid = pwd->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_CLASS p->pw_class = strdup(pwd->pw_class); #endif #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE p->pw_change = pwd->pw_change; #endif #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE p->pw_expire = pwd->pw_expire; #endif p->pw_gecos = strdup(pwd->pw_gecos); p->pw_dir = strdup(pwd->pw_dir); p->pw_shell = strdup(pwd->pw_shell); return true; } static void free_passwd(struct passwd *p) { SAFE_FREE(p->pw_name); SAFE_FREE(p->pw_passwd); #ifdef HAVE_STRUCT_PASSWD_PW_CLASS SAFE_FREE(p->pw_class); #endif SAFE_FREE(p->pw_gecos); SAFE_FREE(p->pw_dir); SAFE_FREE(p->pw_shell); } static void free_passwds(struct passwd *pwds, size_t num_pwds) { size_t i; for(i = 0; i < num_pwds; i++) { free_passwd(&pwds[i]); } free(pwds); } static void print_passwd(struct passwd *pwd) { (void)pwd; DEBUG("%s:%s:%lu:%lu:%s:%s:%s\n", pwd->pw_name, pwd->pw_passwd, (unsigned long)pwd->pw_uid, (unsigned long)pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); } static bool test_nwrap_getpwnam(const char *name, struct passwd *pwd_p) { struct passwd *pwd = NULL; bool ok; DEBUG("Testing getpwnam: %s\n", name); pwd = getpwnam(name); if (pwd == NULL) { return false; } print_passwd(pwd); if (pwd_p == NULL) { return true; } ok = copy_passwd(pwd, pwd_p); return ok; } static void test_nwrap_getpwnam_r(const char *name, struct passwd *pwd_p) { struct passwd pwd, *pwdp; char buffer[4096]; int ret; DEBUG("Testing getpwnam_r: %s\n", name); ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } print_passwd(&pwd); if (pwd_p) { copy_passwd(&pwd, pwd_p); } } static bool test_nwrap_getpwuid(uid_t uid, struct passwd *pwd_p) { struct passwd *pwd = NULL; bool ok; DEBUG("Testing getpwuid: %lu\n", (unsigned long)uid); pwd = getpwuid(uid); if (pwd == NULL) { return false; } print_passwd(pwd); if (pwd_p == NULL) { return true; } ok = copy_passwd(pwd, pwd_p); return ok; } static bool test_nwrap_getpwuid_r(uid_t uid, struct passwd *pwd_p) { struct passwd pwd, *pwdp; char buffer[4096]; int ret; DEBUG("Testing getpwuid_r: %lu\n", (unsigned long)uid); ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } print_passwd(&pwd); if (pwd_p) { copy_passwd(&pwd, pwd_p); } return true; } static bool copy_group(const struct group *grp, struct group *g) { int i; g->gr_name = strdup(grp->gr_name); g->gr_passwd = strdup(grp->gr_passwd); g->gr_gid = grp->gr_gid; g->gr_mem = NULL; for (i = 0; grp->gr_mem != NULL && grp->gr_mem[i] != NULL; i++) { char **mem; mem = realloc(g->gr_mem, sizeof(char *) * (i + 2)); assert_non_null(mem); g->gr_mem = mem; g->gr_mem[i] = strdup(grp->gr_mem[i]); assert_non_null(g->gr_mem[i]); g->gr_mem[i + 1] = NULL; } return true; } static void free_group(struct group *g) { SAFE_FREE(g->gr_name); SAFE_FREE(g->gr_passwd); if (g->gr_mem != NULL) { int i; for (i = 0; g->gr_mem[i] != NULL; i++) { SAFE_FREE(g->gr_mem[i]); } SAFE_FREE(g->gr_mem); } } static void free_groups(struct group *grps, size_t num_grps) { size_t i; for(i = 0; i < num_grps; i++) { free_group(&grps[i]); } free(grps); } static void print_group(struct group *grp) { int i; DEBUG("%s:%s:%lu:", grp->gr_name, grp->gr_passwd, (unsigned long)grp->gr_gid); if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) { DEBUG("\n"); return; } for (i=0; grp->gr_mem[i+1]; i++) { DEBUG("%s,", grp->gr_mem[i]); } DEBUG("%s\n", grp->gr_mem[i]); } static bool test_nwrap_getgrnam(const char *name, struct group *grp_p) { struct group *grp = NULL; bool ok; DEBUG("Testing getgrnam: %s\n", name); grp = getgrnam(name); if (grp == NULL) { return false; } print_group(grp); if (grp_p == NULL) { return true; } ok = copy_group(grp, grp_p); return ok; } static bool test_nwrap_getgrnam_r(const char *name, struct group *grp_p) { struct group grp, *grpp; char buffer[4096]; int ret; DEBUG("Testing getgrnam_r: %s\n", name); ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } print_group(&grp); if (grp_p) { copy_group(&grp, grp_p); } return true; } static bool test_nwrap_getgrgid(gid_t gid, struct group *grp_p) { struct group *grp = NULL; bool ok; DEBUG("Testing getgrgid: %lu\n", (unsigned long)gid); grp = getgrgid(gid); if (grp == NULL) { return false; } print_group(grp); if (grp_p == NULL) { return true; } ok = copy_group(grp, grp_p); return ok; } static bool test_nwrap_getgrgid_r(gid_t gid, struct group *grp_p) { struct group grp, *grpp; char buffer[4096]; int ret; DEBUG("Testing getgrgid_r: %lu\n", (unsigned long)gid); ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } print_group(&grp); if (grp_p) { copy_group(&grp, grp_p); } return true; } static bool test_nwrap_enum_passwd(struct passwd **pwd_array_p, size_t *num_pwd_p) { struct passwd *pwd; struct passwd *pwd_array = NULL; size_t num_pwd = 0; DEBUG("Testing setpwent\n"); setpwent(); while ((pwd = getpwent()) != NULL) { DEBUG("Testing getpwent\n"); print_passwd(pwd); if (pwd_array_p && num_pwd_p) { pwd_array = realloc(pwd_array, sizeof(struct passwd) * (num_pwd + 1)); assert_non_null(pwd_array); copy_passwd(pwd, &pwd_array[num_pwd]); num_pwd++; } } DEBUG("Testing endpwent\n"); endpwent(); if (pwd_array_p) { *pwd_array_p = pwd_array; } if (num_pwd_p) { *num_pwd_p = num_pwd; } return true; } static bool test_nwrap_enum_r_passwd(struct passwd **pwd_array_p, size_t *num_pwd_p) { struct passwd pwd, *pwdp; struct passwd *pwd_array = NULL; size_t num_pwd = 0; char buffer[4096]; int ret; DEBUG("Testing setpwent\n"); setpwent(); while (1) { DEBUG("Testing getpwent_r\n"); #ifdef HAVE_SOLARIS_GETPWENT_R pwdp = getpwent_r(&pwd, buffer, sizeof(buffer)); if (pwdp == NULL) { break; } #else ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } break; } #endif print_passwd(&pwd); if (pwd_array_p && num_pwd_p) { pwd_array = realloc(pwd_array, sizeof(struct passwd) * (num_pwd + 1)); assert_non_null(pwd_array); copy_passwd(&pwd, &pwd_array[num_pwd]); num_pwd++; } } DEBUG("Testing endpwent\n"); endpwent(); if (pwd_array_p) { *pwd_array_p = pwd_array; } if (num_pwd_p) { *num_pwd_p = num_pwd; } return true; } static bool test_nwrap_passwd(void) { struct passwd *pwd, pwd1, pwd2; size_t i, num_pwd; test_nwrap_enum_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); free_passwd(&pwd1); free_passwd(&pwd2); } free_passwds(pwd, num_pwd); return true; } static void test_nwrap_passwd_r(void) { struct passwd *pwd, pwd1, pwd2; size_t i, num_pwd; test_nwrap_enum_r_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam_r(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid_r(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); free_passwd(&pwd1); free_passwd(&pwd2); } free_passwds(pwd, num_pwd); } static bool test_nwrap_passwd_r_cross(void) { struct passwd *pwd, pwd1, pwd2, pwd3, pwd4; size_t i, num_pwd; test_nwrap_enum_r_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam_r(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid_r(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); test_nwrap_getpwnam(pwd[i].pw_name, &pwd3); assert_passwd_equal(&pwd[i], &pwd3); test_nwrap_getpwuid(pwd[i].pw_uid, &pwd4); assert_passwd_equal(&pwd[i], &pwd4); assert_passwd_equal(&pwd3, &pwd4); free_passwd(&pwd1); free_passwd(&pwd2); free_passwd(&pwd3); free_passwd(&pwd4); } free_passwds(pwd, num_pwd); return true; } static bool test_nwrap_enum_group(struct group **grp_array_p, size_t *num_grp_p) { struct group *grp; struct group *grp_array = NULL; size_t num_grp = 0; DEBUG("Testing setgrent\n"); setgrent(); while ((grp = getgrent()) != NULL) { DEBUG("Testing getgrent\n"); print_group(grp); if (grp_array_p && num_grp_p) { grp_array = realloc(grp_array, sizeof(struct group) * (num_grp + 1)); assert_non_null(grp_array); copy_group(grp, &grp_array[num_grp]); num_grp++; } } DEBUG("Testing endgrent\n"); endgrent(); if (grp_array_p) { *grp_array_p = grp_array; } if (num_grp_p) { *num_grp_p = num_grp; } return true; } static bool test_nwrap_enum_r_group(struct group **grp_array_p, size_t *num_grp_p) { struct group grp, *grpp; struct group *grp_array = NULL; size_t num_grp = 0; char buffer[4096]; int ret; DEBUG("Testing setgrent\n"); setgrent(); while (1) { DEBUG("Testing getgrent_r\n"); #ifdef HAVE_SOLARIS_GETGRENT_R grpp = getgrent_r(&grp, buffer, sizeof(buffer)); if (grpp == NULL) { break; } #else ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } break; } #endif print_group(&grp); if (grp_array_p && num_grp_p) { grp_array = realloc(grp_array, sizeof(struct group) * (num_grp + 1)); assert_non_null(grp_array); copy_group(&grp, &grp_array[num_grp]); num_grp++; } } DEBUG("Testing endgrent\n"); endgrent(); if (grp_array_p) { *grp_array_p = grp_array; } if (num_grp_p) { *num_grp_p = num_grp; } return true; } static bool test_nwrap_group(void) { struct group *grp, grp1, grp2; size_t i, num_grp; test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); free_group(&grp1); free_group(&grp2); } free_groups(grp, num_grp); return true; } static bool test_nwrap_group_r(void) { struct group *grp, grp1, grp2; size_t i, num_grp; test_nwrap_enum_r_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam_r(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid_r(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); free_group(&grp1); free_group(&grp2); } free_groups(grp, num_grp); return true; } static bool test_nwrap_group_r_cross(void) { struct group *grp, grp1, grp2, grp3, grp4; size_t i, num_grp; test_nwrap_enum_r_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam_r(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid_r(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); test_nwrap_getgrnam(grp[i].gr_name, &grp3); assert_group_equal(&grp[i], &grp3); test_nwrap_getgrgid(grp[i].gr_gid, &grp4); assert_group_equal(&grp[i], &grp4); assert_group_equal(&grp3, &grp4); free_group(&grp1); free_group(&grp2); free_group(&grp3); free_group(&grp4); } free_groups(grp, num_grp); return true; } #ifdef HAVE_GETGROUPLIST static bool test_nwrap_getgrouplist(const char *user, gid_t gid, gid_t **gids_p, int *num_gids_p) { int ret; int num_groups = 0; gid_t *groups = NULL; DEBUG("Testing getgrouplist: %s\n", user); ret = getgrouplist(user, gid, NULL, &num_groups); if (ret == -1 || num_groups != 0) { groups = malloc(sizeof(gid_t) * num_groups); assert_non_null(groups); ret = getgrouplist(user, gid, groups, &num_groups); } assert_false(ret == -1); DEBUG("%s is member in %d groups\n", user, num_groups); if (gids_p) { *gids_p = groups; } if (num_gids_p) { *num_gids_p = num_groups; } return true; } static bool test_nwrap_user_in_group(const struct passwd *pwd, const struct group *grp) { int i; for (i = 0; grp->gr_mem != NULL && grp->gr_mem[i] != NULL; i++) { if (strcmp(grp->gr_mem[i], pwd->pw_name) == 0) { return true; } } return false; } static bool test_nwrap_membership_user(const struct passwd *pwd, struct group *grp_array, size_t num_grp) { int num_user_groups = 0; size_t num_user_groups_from_enum = 0; gid_t *user_groups = NULL; size_t i; int g; bool primary_group_had_user_member = false; test_nwrap_getgrouplist(pwd->pw_name, pwd->pw_gid, &user_groups, &num_user_groups); for (g=0; g < num_user_groups; g++) { test_nwrap_getgrgid(user_groups[g], NULL); } free(user_groups); for (i=0; i < num_grp; i++) { struct group grp = grp_array[i]; if (test_nwrap_user_in_group(pwd, &grp)) { struct group current_grp; num_user_groups_from_enum++; test_nwrap_getgrnam(grp.gr_name, ¤t_grp); if (current_grp.gr_gid == pwd->pw_gid) { DEBUG("primary group %s of user %s lists user as member\n", current_grp.gr_name, pwd->pw_name); primary_group_had_user_member = true; } free_group(¤t_grp); continue; } } if (!primary_group_had_user_member) { num_user_groups_from_enum++; } assert_int_equal(num_user_groups, num_user_groups_from_enum); return true; } static void test_nwrap_membership(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); struct passwd *pwd; size_t num_pwd; struct group *grp; size_t num_grp; size_t i; (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_enum_passwd(&pwd, &num_pwd); test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_pwd; i++) { test_nwrap_membership_user(&pwd[i], grp, num_grp); } free_passwds(pwd, num_pwd); free_groups(grp, num_grp); } #endif /* HAVE_GETGROUPLIST */ static void test_nwrap_enumeration(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_passwd(); test_nwrap_group(); } static void test_nwrap_reentrant_enumeration(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } DEBUG("Testing re-entrant calls\n"); test_nwrap_passwd_r(); test_nwrap_group_r(); } static void test_nwrap_reentrant_enumeration_crosschecks(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } DEBUG("Testing re-entrant calls with cross checks\n"); test_nwrap_passwd_r_cross(); test_nwrap_group_r_cross(); } static bool test_nwrap_passwd_duplicates(void) { struct passwd *pwd; size_t d, i, num_pwd; int duplicates = 0; test_nwrap_enum_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { const char *current_name = pwd[i].pw_name; for (d=0; d < num_pwd; d++) { const char *dup_name = pwd[d].pw_name; if (d == i) { continue; } if (strcmp(current_name, dup_name) != 0) { continue; } DEBUG("found duplicate names:"); print_passwd(&pwd[d]); print_passwd(&pwd[i]); duplicates++; } } free_passwds(pwd, num_pwd); assert_false(duplicates); return true; } static bool test_nwrap_group_duplicates(void) { struct group *grp; size_t d, i, num_grp; int duplicates = 0; test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { const char *current_name = grp[i].gr_name; for (d=0; d < num_grp; d++) { const char *dup_name = grp[d].gr_name; if (d == i) { continue; } if (strcmp(current_name, dup_name) != 0) { continue; } DEBUG("found duplicate names:"); print_group(&grp[d]); print_group(&grp[i]); duplicates++; } } free_groups(grp, num_grp); assert_false(duplicates); return true; } static void test_nwrap_duplicates(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_passwd_duplicates(); test_nwrap_group_duplicates(); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_enumeration), cmocka_unit_test(test_nwrap_reentrant_enumeration), cmocka_unit_test(test_nwrap_reentrant_enumeration_crosschecks), #ifdef HAVE_GETGROUPLIST cmocka_unit_test(test_nwrap_membership), #endif cmocka_unit_test(test_nwrap_duplicates), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.3/.clang_complete000644 001750 000144 00000000067 12254017317 017021 0ustar00asnusers000000 000000 -DHAVE_IPV6 -DHAVE_LIBNSL -DHAVE_LIBSOCKET -Isrc -Iobj nss_wrapper-1.1.3/nss_wrapper-config-version.cmake.in000644 001750 000144 00000000611 12267205751 022744 0ustar00asnusers000000 000000 set(PACKAGE_VERSION @APPLICATION_VERSION@) # Check whether the requested PACKAGE_FIND_VERSION is compatible 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) endif() endif() nss_wrapper-1.1.3/CPackConfig.cmake000644 001750 000144 00000003765 12274207162 017166 0ustar00asnusers000000 000000 # For help take a look at: # http://www.cmake.org/Wiki/CMake:CPackConfiguration ### general settings set(CPACK_PACKAGE_NAME ${APPLICATION_NAME}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README") set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team") set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") ### versions set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${APPLICATION_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") ### source generator set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") if (WIN32) set(CPACK_GENERATOR "ZIP") ### nsis generator find_package(NSIS) if (NSIS_MAKE) set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS") set(CPACK_NSIS_DISPLAY_NAME "The SSH Library") set(CPACK_NSIS_COMPRESSOR "/SOLID zlib") set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage") endif (NSIS_MAKE) endif (WIN32) set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh") set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION}) set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers") set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "Libraries used to build programs which use libssh") set(CPACK_COMPONENT_HEADERS_DESCRIPTION "C/C++ header files for use with libssh") set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) #set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime") set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") set(CPACK_COMPONENT_HEADERS_GROUP "Development") include(CPack) nss_wrapper-1.1.3/nss_wrapper.pc.cmake000644 001750 000144 00000000207 12274207162 020007 0ustar00asnusers000000 000000 Name: @APPLICATION_NAME@ Description: The nss_wrapper library Version: @APPLICATION_VERSION@ Libs: @LIB_INSTALL_DIR@/@NSS_WRAPPER_LIB@ nss_wrapper-1.1.3/.ycm_extra_conf.py000644 001750 000144 00000006420 12317456564 017506 0ustar00asnusers000000 000000 import os import ycm_core flags = [ ] # Set this to the absolute path to the folder (NOT the file!) containing the # compile_commands.json file to use that instead of 'flags'. See here for # more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html # # Most projects will NOT need to set this to anything; you can just change the # 'flags' list of compilation flags. Notice that YCM itself uses that approach. compilation_database_folder = 'obj' if os.path.exists( compilation_database_folder ): database = ycm_core.CompilationDatabase( compilation_database_folder ) else: database = None SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] def DirectoryOfThisScript(): return os.path.dirname( os.path.abspath( __file__ ) ) def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): if not working_directory: return list( flags ) new_flags = [] make_next_absolute = False path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] for flag in flags: new_flag = flag if make_next_absolute: make_next_absolute = False if not flag.startswith( '/' ): new_flag = os.path.join( working_directory, flag ) for path_flag in path_flags: if flag == path_flag: make_next_absolute = True break if flag.startswith( path_flag ): path = flag[ len( path_flag ): ] new_flag = path_flag + os.path.join( working_directory, path ) break if new_flag: new_flags.append( new_flag ) return new_flags def IsHeaderFile( filename ): extension = os.path.splitext( filename )[ 1 ] return extension in [ '.h', '.hxx', '.hpp', '.hh' ] def GetCompilationInfoForFile( filename ): # The compilation_commands.json file generated by CMake does not have entries # for header files. So we do our best by asking the db for flags for a # corresponding source file, if any. If one exists, the flags for that file # should be good enough. if IsHeaderFile( filename ): basename = os.path.splitext( filename )[ 0 ] for extension in SOURCE_EXTENSIONS: replacement_file = basename + extension if os.path.exists( replacement_file ): compilation_info = database.GetCompilationInfoForFile( replacement_file ) if compilation_info.compiler_flags_: return compilation_info return None return database.GetCompilationInfoForFile( filename ) def FlagsForFile( filename, **kwargs ): if database: # Bear in mind that compilation_info.compiler_flags_ does NOT return a # python list, but a "list-like" StringVec object compilation_info = GetCompilationInfoForFile( filename ) if not compilation_info: return None final_flags = MakeRelativePathsInFlagsAbsolute( compilation_info.compiler_flags_, compilation_info.compiler_working_dir_ ) # NOTE: This is just for YouCompleteMe; it's highly likely that your project # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. try: final_flags.remove( '-stdlib=libc++' ) except ValueError: pass else: relative_to = DirectoryOfThisScript() final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) return { 'flags': final_flags, 'do_cache': True } nss_wrapper-1.1.3/.ycm_extra_conf.pyc000644 001750 000144 00000005213 12320723760 017635 0ustar00asnusers000000 000000 ó t]>Sc@s—ddlZddlZgZdZejjeƒrHejeƒZndZddddddgZ d „Z d „Z d „Z d „Z d „ZdS(iÿÿÿÿNtobjs.cpps.cxxs.ccs.cs.ms.mmcCstjjtjjtƒƒS(N(tostpathtdirnametabspatht__file__(((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pytDirectoryOfThisScriptsc Csø|st|ƒSg}t}ddddg}xÃ|D]»}|}|rwt}|jdƒswtjj||ƒ}qwnx`|D]X}||kršt}Pn|j|ƒr~|t|ƒ}|tjj||ƒ}Pq~q~W|r5|j|ƒq5q5W|S(Ns-isystems-Is-iquotes --sysroot=t/( tlisttFalset startswithRRtjointTruetlentappend( tflagstworking_directoryt new_flagstmake_next_absolutet path_flagstflagtnew_flagt path_flagR((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pyt MakeRelativePathsInFlagsAbsolutes,    cCs tjj|ƒd}|dkS(Nis.hs.hxxs.hpps.hh(s.hs.hxxs.hpps.hh(RRtsplitext(tfilenamet extension((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pyt IsHeaderFile7scCst|ƒrrtjj|ƒd}xItD]A}||}tjj|ƒr)tj|ƒ}|jrj|Sq)q)WdStj|ƒS(Ni( RRRRtSOURCE_EXTENSIONStexiststdatabasetGetCompilationInfoForFiletcompiler_flags_tNone(RtbasenameRtreplacement_filetcompilation_info((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pyR<s      cKsƒtrYt|ƒ}|sdSt|j|jƒ}y|jdƒWqqtk rUqqXntƒ}tt |ƒ}i|d6t d6S(Ns-stdlib=libc++Rtdo_cache( RRR!RR tcompiler_working_dir_tremovet ValueErrorRRR (RtkwargsR$t final_flagst relative_to((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pyt FlagsForFileNs     (Rtycm_coreRtcompilation_database_folderRRtCompilationDatabaseRR!RRRRRR,(((s;/home/asn/workspace/projects/nss_wrapper/.ycm_extra_conf.pyts       nss_wrapper-1.1.3/README.install000644 001750 000144 00000003556 12342110056 016367 0ustar00asnusers000000 000000 Obtaining the sources ===================== Source tarballs for nss_wrapper can be downloaded from https://ftp.samba.org/pub/cwrap/ The source code repository for socket wrapper is located under git://git.samba.org/nss_wrapper.git To create a local copy, run $ git clone git://git.samba.org/nss_wrapper.git $ cd nss_wrapper Building from sources ===================== nss_wrapper uses cmake (www.cmake.org) as its build system. In an unpacked sources base directory, create a directory to contain the build results, e.g. $ mkdir obj $ cd obj Note that "obj" is just an example. The directory can be named arbitrarily. Next, run cmake to configure the build, e.g. $ cmake -DCMAKE_INSTALL_PREFIX= .. or on a 64 bit red hat system: $ cmake -DCMAKE_INSTALL_PREFIX= -DLIB_SUFFIX=64 .. The "" should be replaced by the intended installation target prefix directory, typically /usr or /usr/local. Note that the target directory does not have to be a direct or indirect subdirectory of the source base directory: It can be an arbitrary directory in the system. In the general case, ".." has to be replaced by a relative or absolute path of the source base directory in the "cmake" command line. One can control the build type with "-DCMAKE_BUILD_TYPE=" where can be one of Debug, Release, RelWithDebInfo, and some more (see cmake.org). The default is "RelWithDebInfo". After configuring with cmake, run the build with $ make Unit testing ============ In order to support running the test suite after building, the cmocka unit test framework needs to be installed (cmocka.org), and you need to specify -DUNIT_TESTING=ON in the cmake run. After running "make", $ make test runs the test suite. Installing ========== nss_wrapper is installed into the prefix directory after running "cmake" and "make" with $ make install nss_wrapper-1.1.3/nss_wrapper-config.cmake.in000644 001750 000144 00000000075 12342110056 021250 0ustar00asnusers000000 000000 set(NSS_WRAPPER_LIBRARY @LIB_INSTALL_DIR@/@NSS_WRAPPER_LIB@) nss_wrapper-1.1.3/TODO000644 001750 000144 00000000377 12412242573 014540 0ustar00asnusers000000 000000 TODO ===== Library -------- * None at the moment. Testing -------- * Split the testsuite in several tests. * Add missing tests. Check the code coverage on http://mock.cryptomilk.org/index.php?project=nsswrapper to see what tests are still needed. nss_wrapper-1.1.3/README000644 001750 000144 00000000723 12415432734 014726 0ustar00asnusers000000 000000 NSS_WRAPPER =========== This is a wrapper for the user, group and hosts NSS API. DESCRIPTION ----------- More details can be found in the manpage: man -l ./doc/nss_wrapper.1 or the raw text version: less ./doc/nss_wrapper.1.txt For installation instructions please take a look at the README.install file. MAILINGLIST ----------- As the mailing list samba-technical is used and can be found here: https://lists.samba.org/mailman/listinfo/samba-technical nss_wrapper-1.1.3/doc/000755 001750 000144 00000000000 12672772135 014620 5ustar00asnusers000000 000000 nss_wrapper-1.1.3/doc/CMakeLists.txt000644 001750 000144 00000000141 12415432734 017345 0ustar00asnusers000000 000000 install(FILES nss_wrapper.1 DESTINATION ${MAN_INSTALL_DIR}/man1) nss_wrapper-1.1.3/doc/README000644 001750 000144 00000000201 12415432734 015462 0ustar00asnusers000000 000000 The manpage is written with asciidoc. To generate the manpage use: a2x --doctype manpage --format manpage doc/nss_wrapper.1.txt nss_wrapper-1.1.3/doc/nss_wrapper.1000644 001750 000144 00000013015 12620616655 017242 0ustar00asnusers000000 000000 '\" t .\" Title: nss_wrapper .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2015-09-12 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" .TH "NSS_WRAPPER" "1" "2015\-09\-12" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nss_wrapper \- A wrapper for the user, group and hosts NSS API .SH "SYNOPSIS" .sp LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_PASSWD=/path/to/passwd NSS_WRAPPER_GROUP=/path/to/group NSS_WRAPPER_HOSTS=/path/to/host \fB\&./myapplication\fR .SH "DESCRIPTION" .sp There are projects which provide daemons needing to be able to create, modify and delete Unix users\&. Or just switch user ids to interact with the system e\&.g\&. a user space file server\&. To be able to test that you need the privilege to modify the passwd and groups file\&. With nss_wrapper it is possible to define your own passwd and groups file which will be used by software to act correctly while under test\&. .sp If you have a client and server under test they normally use functions to resolve network names to addresses (dns) or vice versa\&. The nss_wrappers allow you to create a hosts file to setup name resolution for the addresses you use with socket_wrapper\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Provides information for user and group accounts\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Network name resolution using a hosts file\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Loading and testing of NSS modules\&. .RE .SH "LIMITATIONS" .sp Some calls in nss_wrapper will only work if uid_wrapper is loaded and active\&. One of this functions is initgroups() which needs to run setgroups() to set the groups for the user\&. setgroups() is wrapped by uid_wrapper\&. .SH "ENVIRONMENT VARIABLES" .PP \fBNSS_WRAPPER_PASSWD\fR, \fBNSS_WRAPPER_GROUP\fR .RS 4 For user and group accounts you need to create two files: \fIpasswd\fR and \fIgroup\fR\&. The format of the passwd file is described in \fIman 5 passwd\fR and the group file in \fIman 5 group\fR\&. So you can fill these files with made up accounts\&. You point nss_wrapper to them using the two variables NSS_WRAPPER_PASSWD=/path/to/your/passwd and NSS_WRAPPER_GROUP=/path/to/your/group\&. .RE .PP \fBNSS_WRAPPER_HOSTS\fR .RS 4 If you also need to emulate network name resolution in your enviornment, especially with socket_wrapper, you can write a hosts file\&. The format is described in \fIman 5 hosts\fR\&. Then you can point nss_wrapper to your hosts file using: NSS_WRAPPER_HOSTS=/path/to/your/hosts .RE .PP \fBNSS_WRAPPER_HOSTNAME\fR .RS 4 If you need to return a hostname which is different from the one of your machine is using you can use: NSS_WRAPPER_HOSTNAME=test\&.example\&.org .RE .PP \fBNSS_WRAPPER_MODULE_SO_PATH\fR, \fBNSS_WRAPPER_MODULE_FN_PREFIX\fR .RS 4 If you have a project which also provides user and group information out of a database, you normally write your own nss modules\&. nss_wrapper is able to load nss modules and ask them first before looking into the faked passwd and group file\&. To point nss_wrapper to the module you can do that using NSS_WRAPPER_MODULE_SO_PATH=/path/to/libnss_yourmodule\&.so\&. As each nss module has a special prefix like _nss_winbind_getpwnam() you need to set the prefix too so nss_wrapper can load the functions with NSS_WRAPPER_MODULE_FN_PREFIX=\&. .RE .sp For _nss_winbind_getpwnam() this would be: .sp .if n \{\ .RS 4 .\} .nf NSS_WRAPPER_MODULE_FN_PREFIX=winbind .fi .if n \{\ .RE .\} .PP \fBNSS_WRAPPER_DEBUGLEVEL\fR .RS 4 If you need to see what is going on in nss_wrapper itself or try to find a bug, you can enable logging support in nss_wrapper if you built it with debug symbols\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 0 = ERROR .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 1 = WARNING .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 2 = DEBUG .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 3 = TRACE .RE .RE .SH "EXAMPLE" .sp .if n \{\ .RS 4 .\} .nf $ echo "bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false" > passwd $ echo "root:x:65534:65532:root gecos:/home/test/root:/bin/false" >> passwd $ echo "users:x:1000:" > group $ echo "root:x:65532:" >> group $ LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_PASSWD=passwd \e NSS_WRAPPER_GROUP=group getent passwd bob bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false $ LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_HOSTNAME=test\&.example\&.org hostname test\&.example\&.org .fi .if n \{\ .RE .\} nss_wrapper-1.1.3/doc/nss_wrapper.1.txt000644 001750 000144 00000007172 12620616655 020067 0ustar00asnusers000000 000000 nss_wrapper(1) ============== :revdate: 2015-09-12 NAME ---- nss_wrapper - A wrapper for the user, group and hosts NSS API SYNOPSIS -------- LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=/path/to/passwd NSS_WRAPPER_GROUP=/path/to/group NSS_WRAPPER_HOSTS=/path/to/host *./myapplication* DESCRIPTION ----------- There are projects which provide daemons needing to be able to create, modify and delete Unix users. Or just switch user ids to interact with the system e.g. a user space file server. To be able to test that you need the privilege to modify the passwd and groups file. With nss_wrapper it is possible to define your own passwd and groups file which will be used by software to act correctly while under test. If you have a client and server under test they normally use functions to resolve network names to addresses (dns) or vice versa. The nss_wrappers allow you to create a hosts file to setup name resolution for the addresses you use with socket_wrapper. - Provides information for user and group accounts. - Network name resolution using a hosts file. - Loading and testing of NSS modules. LIMITATIONS ----------- Some calls in nss_wrapper will only work if uid_wrapper is loaded and active. One of this functions is initgroups() which needs to run setgroups() to set the groups for the user. setgroups() is wrapped by uid_wrapper. ENVIRONMENT VARIABLES --------------------- *NSS_WRAPPER_PASSWD*:: *NSS_WRAPPER_GROUP*:: For user and group accounts you need to create two files: 'passwd' and 'group'. The format of the passwd file is described in 'man 5 passwd' and the group file in 'man 5 group'. So you can fill these files with made up accounts. You point nss_wrapper to them using the two variables NSS_WRAPPER_PASSWD=/path/to/your/passwd and NSS_WRAPPER_GROUP=/path/to/your/group. *NSS_WRAPPER_HOSTS*:: If you also need to emulate network name resolution in your enviornment, especially with socket_wrapper, you can write a hosts file. The format is described in 'man 5 hosts'. Then you can point nss_wrapper to your hosts file using: NSS_WRAPPER_HOSTS=/path/to/your/hosts *NSS_WRAPPER_HOSTNAME*:: If you need to return a hostname which is different from the one of your machine is using you can use: NSS_WRAPPER_HOSTNAME=test.example.org *NSS_WRAPPER_MODULE_SO_PATH*:: *NSS_WRAPPER_MODULE_FN_PREFIX*:: If you have a project which also provides user and group information out of a database, you normally write your own nss modules. nss_wrapper is able to load nss modules and ask them first before looking into the faked passwd and group file. To point nss_wrapper to the module you can do that using NSS_WRAPPER_MODULE_SO_PATH=/path/to/libnss_yourmodule.so. As each nss module has a special prefix like _nss_winbind_getpwnam() you need to set the prefix too so nss_wrapper can load the functions with NSS_WRAPPER_MODULE_FN_PREFIX=. For _nss_winbind_getpwnam() this would be: NSS_WRAPPER_MODULE_FN_PREFIX=winbind *NSS_WRAPPER_DEBUGLEVEL*:: If you need to see what is going on in nss_wrapper itself or try to find a bug, you can enable logging support in nss_wrapper if you built it with debug symbols. - 0 = ERROR - 1 = WARNING - 2 = DEBUG - 3 = TRACE EXAMPLE ------- $ echo "bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false" > passwd $ echo "root:x:65534:65532:root gecos:/home/test/root:/bin/false" >> passwd $ echo "users:x:1000:" > group $ echo "root:x:65532:" >> group $ LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=passwd \ NSS_WRAPPER_GROUP=group getent passwd bob bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false $ LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_HOSTNAME=test.example.org hostname test.example.org nss_wrapper-1.1.3/AUTHORS000644 001750 000144 00000000250 12622316322 015103 0ustar00asnusers000000 000000 Stefan Metzmacher Guenther Deschner Andreas Schneider Robin Hack Michael Adam nss_wrapper-1.1.3/CTestConfig.cmake000644 001750 000144 00000000420 12623556624 017220 0ustar00asnusers000000 000000 set(UPDATE_TYPE "true") set(CTEST_PROJECT_NAME "nsswrapper") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_DROP_METHOD "https") set(CTEST_DROP_SITE "mock.cryptomilk.org") set(CTEST_DROP_LOCATION "/submit.php?project=nsswrapper") set(CTEST_DROP_SITE_CDASH TRUE) nss_wrapper-1.1.3/ConfigureChecks.cmake000644 001750 000144 00000017530 12672602321 020112 0ustar00asnusers000000 000000 include(CheckIncludeFile) include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) include(CheckStructHasMember) include(CheckPrototypeDefinition) include(TestBigEndian) set(PACKAGE ${APPLICATION_NAME}) set(VERSION ${APPLICATION_VERSION}) set(DATADIR ${DATA_INSTALL_DIR}) set(LIBDIR ${LIB_INSTALL_DIR}) set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}") set(SYSCONFDIR ${SYSCONF_INSTALL_DIR}) set(BINARYDIR ${CMAKE_BINARY_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR}) function(COMPILER_DUMPVERSION _OUTPUT_VERSION) # Remove whitespaces from the argument. # This is needed for CC="ccache gcc" cmake .. string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}") execute_process( COMMAND ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion OUTPUT_VARIABLE _COMPILER_VERSION ) string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" _COMPILER_VERSION "${_COMPILER_VERSION}") set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) endfunction() if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) compiler_dumpversion(GNUCC_VERSION) if (NOT GNUCC_VERSION EQUAL 34) set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden") check_c_source_compiles( "void __attribute__((visibility(\"default\"))) test() {} int main(void){ return 0; } " WITH_VISIBILITY_HIDDEN) set(CMAKE_REQUIRED_FLAGS "") endif (NOT GNUCC_VERSION EQUAL 34) endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) # HEADERS check_include_file(sys/types.h HAVE_SYS_TYPES_H) check_include_file(pwd.h HAVE_PWD_H) check_include_file(shadow.h HAVE_SHADOW_H) check_include_file(grp.h HAVE_GRP_H) check_include_file(nss.h HAVE_NSS_H) check_include_file(nss_common.h HAVE_NSS_COMMON_H) # FUNCTIONS check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF) check_function_exists(getpwnam_r HAVE_GETPWNAM_R) check_function_exists(getpwuid_r HAVE_GETPWUID_R) check_function_exists(getpwent_r HAVE_GETPWENT_R) check_function_exists(setspent HAVE_SETSPENT) check_function_exists(getspnam HAVE_GETSPNAM) check_function_exists(getgrnam_r HAVE_GETGRNAM_R) check_function_exists(getgrgid_r HAVE_GETGRGID_R) check_function_exists(getgrent_r HAVE_GETGRENT_R) check_function_exists(getgrouplist HAVE_GETGROUPLIST) check_function_exists(gethostbyaddr_r HAVE_GETHOSTBYADDR_R) check_function_exists(gethostbyname_r HAVE_GETHOSTBYNAME_R) check_function_exists(gethostbyname2 HAVE_GETHOSTBYNAME2) if (WIN32) check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) check_function_exists(_vsnprintf HAVE__VSNPRINTF) check_function_exists(_snprintf HAVE__SNPRINTF) check_function_exists(_snprintf_s HAVE__SNPRINTF_S) endif (WIN32) if (UNIX) if (NOT LINUX) # libsocket (Solaris) check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET) if (HAVE_LIBSOCKET) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket) endif (HAVE_LIBSOCKET) # libnsl/inet_pton (Solaris) check_library_exists(nsl inet_pton "" HAVE_LIBNSL) if (HAVE_LIBNSL) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl) endif (HAVE_LIBNSL) endif (NOT LINUX) check_function_exists(getaddrinfo HAVE_GETADDRINFO) endif (UNIX) if (SOLARIS) check_function_exists(__posix_getpwnam_r HAVE___POSIX_GETPWNAM_R) check_function_exists(__posix_getpwuid_r HAVE___POSIX_GETPWUID_R) check_function_exists(__posix_getgrgid_r HAVE___POSIX_GETGRGID_R) check_function_exists(__posix_getgrnam_r HAVE___POSIX_GETGRNAM_R) endif (SOLARIS) check_function_exists(asprintf HAVE_ASPRINTF) if (UNIX AND HAVE_ASPRINTF) add_definitions(-D_GNU_SOURCE) endif (UNIX AND HAVE_ASPRINTF) set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_PTHREAD_SEMANTICS) check_prototype_definition(getpwent_r "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)" "NULL" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWENT_R) check_prototype_definition(getpwnam_r "int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)" "-1" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWNAM_R) check_prototype_definition(getpwuid_r "int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)" "-1" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWUID_R) check_prototype_definition(getgrent_r "struct group *getgrent_r(struct group *src, char *buf, int buflen)" "NULL" "unistd.h;grp.h" HAVE_SOLARIS_GETGRENT_R) check_prototype_definition(getgrnam_r "int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)" "-1" "unistd.h;grp.h" HAVE_SOLARIS_GETGRNAM_R) check_prototype_definition(getgrgid_r "int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)" "-1" "unistd.h;grp.h" HAVE_SOLARIS_GETGRGID_R) check_prototype_definition(sethostent "int sethostent(int stayopen)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_SETHOSTENT) check_prototype_definition(endhostent "int endhostent(void)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_ENDHOSTENT) check_prototype_definition(gethostname "int gethostname(char *name, int len)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_GETHOSTNAME) set(CMAKE_REQUIRED_DEFINITIONS) check_prototype_definition(setgrent "int setgrent(void)" "-1" "unistd.h;grp.h" HAVE_BSD_SETGRENT) check_prototype_definition(getnameinfo "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)" "-1" "unistd.h;netdb.h" HAVE_LINUX_GETNAMEINFO) check_prototype_definition(getnameinfo "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)" "-1" "unistd.h;netdb.h" HAVE_LINUX_GETNAMEINFO_UNSIGNED) # STRUCT MEMBERS check_struct_has_member("struct sockaddr" sa_len "sys/socket.h netinet/in.h" HAVE_STRUCT_SOCKADDR_SA_LEN) check_struct_has_member("struct passwd" pw_class "pwd.h" HAVE_STRUCT_PASSWD_PW_CLASS) check_struct_has_member("struct passwd" pw_change "pwd.h" HAVE_STRUCT_PASSWD_PW_CHANGE) check_struct_has_member("struct passwd" pw_expire "pwd.h" HAVE_STRUCT_PASSWD_PW_EXPIRE) # IPV6 check_c_source_compiles(" #include #include #include #include #include int main(void) { struct sockaddr_storage sa_store; struct addrinfo *ai = NULL; struct in6_addr in6addr; int idx = if_nametoindex(\"iface1\"); int s = socket(AF_INET6, SOCK_STREAM, 0); int ret = getaddrinfo(NULL, NULL, NULL, &ai); if (ret != 0) { const char *es = gai_strerror(ret); } freeaddrinfo(ai); { int val = 1; #ifdef HAVE_LINUX_IPV6_V6ONLY_26 #define IPV6_V6ONLY 26 #endif ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&val, sizeof(val)); } return 0; }" HAVE_IPV6) check_c_source_compiles(" void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2))); int main(void) { return 0; }" HAVE_ATTRIBUTE_PRINTF_FORMAT) check_c_source_compiles(" void test_destructor_attribute(void) __attribute__ ((destructor)); void test_destructor_attribute(void) { return; } int main(void) { return 0; }" HAVE_DESTRUCTOR_ATTRIBUTE) check_library_exists(dl dlopen "" HAVE_LIBDL) if (HAVE_LIBDL) find_library(DLFCN_LIBRARY dl) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${DLFCN_LIBRARY}) endif (HAVE_LIBDL) # ENDIAN if (NOT WIN32) test_big_endian(WORDS_BIGENDIAN) endif (NOT WIN32) set(NWRAP_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "nss_wrapper required system libraries") nss_wrapper-1.1.3/config.h.cmake000644 001750 000144 00000006145 12672602321 016543 0ustar00asnusers000000 000000 /* Name of package */ #cmakedefine PACKAGE "${APPLICATION_NAME}" /* Version number of package */ #cmakedefine VERSION "${APPLICATION_VERSION}" #cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}" #cmakedefine DATADIR "${DATADIR}" #cmakedefine LIBDIR "${LIBDIR}" #cmakedefine PLUGINDIR "${PLUGINDIR}" #cmakedefine SYSCONFDIR "${SYSCONFDIR}" #cmakedefine BINARYDIR "${BINARYDIR}" #cmakedefine SOURCEDIR "${SOURCEDIR}" /************************** HEADER FILES *************************/ #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_PWD_H 1 #cmakedefine HAVE_SHADOW_H 1 #cmakedefine HAVE_GRP_H 1 #cmakedefine HAVE_NSS_H 1 #cmakedefine HAVE_NSS_COMMON_H 1 /*************************** FUNCTIONS ***************************/ /* Define to 1 if you have the `getpwnam_r' function. */ #cmakedefine HAVE_GETPWNAM_R 1 /* Define to 1 if you have the `getpwuid_r' function. */ #cmakedefine HAVE_GETPWUID_R 1 /* Define to 1 if you have the `getpwent_r' function. */ #cmakedefine HAVE_GETPWENT_R 1 /* Define to 1 if you have the `setspent' function. */ #cmakedefine HAVE_SETSPENT 1 /* Define to 1 if you have the `getspnam' function. */ #cmakedefine HAVE_GETSPNAM 1 /* Define to 1 if you have the `getgrnam_r' function. */ #cmakedefine HAVE_GETGRNAM_R 1 /* Define to 1 if you have the `getgrgid_r' function. */ #cmakedefine HAVE_GETGRGID_R 1 /* Define to 1 if you have the `getgrent_r' function. */ #cmakedefine HAVE_GETGRENT_R 1 /* Define to 1 if you have the `getgrouplist' function. */ #cmakedefine HAVE_GETGROUPLIST 1 /* Define to 1 if you have the `gethostbyaddr_r' function. */ #cmakedefine HAVE_GETHOSTBYADDR_R 1 /* Define to 1 if you have the `gethostbyname_r' function. */ #cmakedefine HAVE_GETHOSTBYNAME_R 1 /* Define to 1 if you have the `gethostbyname2' function. */ #cmakedefine HAVE_GETHOSTBYNAME2 1 #cmakedefine HAVE___POSIX_GETPWNAM_R 1 #cmakedefine HAVE___POSIX_GETPWUID_R 1 #cmakedefine HAVE___POSIX_GETGRGID_R 1 #cmakedefine HAVE___POSIX_GETGRNAM_R 1 /*************************** LIBRARIES ***************************/ #cmakedefine HAVE_LIBNSL 1 #cmakedefine HAVE_LIBSOCKET 1 /**************************** OPTIONS ****************************/ #cmakedefine HAVE_SOLARIS_GETPWENT_R 1 #cmakedefine HAVE_SOLARIS_GETPWNAM_R 1 #cmakedefine HAVE_SOLARIS_GETPWUID_R 1 #cmakedefine HAVE_SOLARIS_GETGRENT_R 1 #cmakedefine HAVE_SOLARIS_GETGRNAM_R 1 #cmakedefine HAVE_SOLARIS_GETGRGID_R 1 #cmakedefine HAVE_SOLARIS_SETHOSTENT 1 #cmakedefine HAVE_SOLARIS_ENDHOSTENT 1 #cmakedefine HAVE_SOLARIS_GETHOSTNAME 1 #cmakedefine HAVE_BSD_SETGRENT 1 #cmakedefine HAVE_LINUX_GETNAMEINFO 1 #cmakedefine HAVE_LINUX_GETNAMEINFO_UNSIGNED 1 #cmakedefine HAVE_STRUCT_SOCKADDR_SA_LEN 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_CLASS 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_CHANGE 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_EXPIRE 1 #cmakedefine HAVE_IPV6 1 #cmakedefine HAVE_ATTRIBUTE_PRINTF_FORMAT 1 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1 /*************************** ENDIAN *****************************/ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #cmakedefine WORDS_BIGENDIAN 1 nss_wrapper-1.1.3/ChangeLog000644 001750 000144 00000002763 12672757464 015645 0ustar00asnusers000000 000000 ChangeLog ========== version 1.1.3 (released 2015-03-18) * Added support for BSD 'struct passwd' members * Replaced strcpy() with snprintf() version 1.1.2 (released 2015-12-17) * Fixed segfault while reloading hosts file * Fixed issue where are not fault tolerant if an alias has already been added version 1.1.1 (released 2015-11-23) * Fixed nss_wrapper build on Solaris version 1.1.0 (released 2015-11-20) * Added support for initgroups() * Added support for shadow files (getspnam(), etc.) * Improved support for multi address handling in getaddrinfo() * Improved file parser * Fixed compilation on machines without IPv4 support * Fixed service string sanity check in getaddrinfo() (bso #11501) * Fixed AI_NUMERICHOST handling in getaddrinfo() (bso # 11477) version 1.0.3 (released 2014-09-11) * Added a nss_wrapper manpage. * Fixed cmake find_package configs. * Fixed resolving hostnames with a trailing dot. * Fixed an overflow when checking if a IPv6 address is IPv4. * Fall back to RTLD_NEXT for symbol binding if we can't find libc. version 1.0.2 (released 2014-04-08) * Added public nss_wrapper_enabled(). * Added public nss_wrapper_hosts_enabled(). * Fixed segfault in 'getent hosts' without aliases. * Fixed IPv4 and IPv6 resolving with 'getent ahosts'. version 1.0.1 (released 2014-02-04) * Added --libs to pkg-config. * Added nss_wrapper-config.cmake * Fixed a bug packaging the obj directory. version 1.0.0 (released 2014-02-02) * Initial release nss_wrapper-1.1.3/CMakeLists.txt000644 001750 000144 00000005630 12672757502 016620 0ustar00asnusers000000 000000 project(nss_wrapper C) # Required cmake version cmake_minimum_required(VERSION 2.8.0) # global needed variables set(APPLICATION_NAME ${PROJECT_NAME}) set(APPLICATION_VERSION_MAJOR "1") set(APPLICATION_VERSION_MINOR "1") set(APPLICATION_VERSION_PATCH "3") set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}") # SOVERSION scheme: CURRENT.AGE.REVISION # If there was an incompatible interface change: # Increment CURRENT. Set AGE and REVISION to 0 # If there was a compatible interface change: # Increment AGE. Set REVISION to 0 # If the source code was changed, but there were no interface changes: # Increment REVISION. set(LIBRARY_VERSION "0.2.3") set(LIBRARY_SOVERSION "0") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules ) # add definitions include(DefineCMakeDefaults) include(DefinePlatformDefaults) include(DefineCompilerFlags) include(DefineInstallationPaths) include(DefineOptions.cmake) include(CPackConfig.cmake) # disallow in-source build include(MacroEnsureOutOfSourceBuild) macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") # Find out if we have threading available set(CMAKE_THREAD_PREFER_PTHREADS ON) find_package(Threads) # config.h checks include(ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) # check subdirectories add_subdirectory(src) install( PROGRAMS nss_wrapper.pl DESTINATION ${BIN_INSTALL_DIR}) if (UNIT_TESTING) find_package(CMocka REQUIRED) file(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" VALGRIND_SUPPRESSION_FILE) # add the valgrind suppressions set(MEMORYCHECK_SUPPRESSIONS_FILE ${VALGRIND_SUPPRESSION_FILE} CACHE FILEPATH "Path to the memory checking command, used for memory error detection.") include(AddCMockaTest) add_subdirectory(tests) endif (UNIT_TESTING) # pkg-config file get_filename_component(NSS_WRAPPER_LIB ${NSS_WRAPPER_LOCATION} NAME) configure_file(nss_wrapper.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper.pc @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig COMPONENT pkgconfig ) # cmake config files 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( FILES ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config-version.cmake ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config.cmake DESTINATION ${CMAKE_INSTALL_DIR}/nss_wrapper COMPONENT devel ) add_subdirectory(doc)