-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ca2e537
Showing
9 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build/** | ||
result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
cmake_minimum_required (VERSION 3.3.0) | ||
project (shim-getpw LANGUAGES C) | ||
|
||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) | ||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) | ||
|
||
set(CMAKE_POSITION_INDEPENDENT_CODE ON) | ||
|
||
|
||
add_library(shim-getpw SHARED src/getpw.c) | ||
target_link_libraries(shim-getpw dl) | ||
|
||
add_executable(shim-test-string tests/test-string.c) | ||
add_executable(shim-test-id tests/test-id.c) | ||
|
||
install(TARGETS shim-getpw DESTINATION ${CMAKE_INSTALL_LIBDIR}/) | ||
|
||
# Test runner script run-time dependencies | ||
find_program (BASH_BIN bash) | ||
find_program (GETENT_BIN getent) | ||
find_program (CUT_BIN cut) | ||
|
||
if(BASH_BIN AND GETENT_BIN AND CUT_BIN) | ||
enable_testing() | ||
add_test(NAME all-tests COMMAND ${BASH_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/tests/runner.sh $<TARGET_FILE:shim-getpw> $<TARGET_FILE:shim-test-string> $<TARGET_FILE:shim-test-id>) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ stdenv, cmake | ||
, openssh | ||
}: | ||
stdenv.mkDerivation { | ||
name = "shim-getpw"; | ||
|
||
src = ./.; | ||
|
||
buildInputs = [ | ||
cmake | ||
]; | ||
|
||
doCheck = true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ pkgs ? import <nixpkgs> { } | ||
}: | ||
pkgs.callPackage ./default.nix { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ pkgs ? import <nixpkgs> { } | ||
}: | ||
with pkgs; | ||
stdenv.mkDerivation { | ||
name = "shim-getpwuid-env"; | ||
|
||
buildInputs = [ | ||
(pkgs.callPackage ./default.nix { }).buildInputs | ||
cppcheck | ||
]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#define _GNU_SOURCE | ||
|
||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <inttypes.h> | ||
#include <errno.h> | ||
#include <dlfcn.h> | ||
|
||
#include <sys/types.h> | ||
#include <pwd.h> | ||
|
||
// Helper to convert from environment variable charstrings to uid/gids | ||
intmax_t | ||
str_to_id(const char *id_str) | ||
{ | ||
char *endptr = 0; | ||
errno = 0; | ||
const intmax_t id = strtoimax(id_str, &endptr, 10); | ||
|
||
// TODO log when errors generated? | ||
if ((errno == ERANGE && (id == INTMAX_MAX || id == INTMAX_MIN)) | ||
|| (errno != 0 && id == 0)) { | ||
// Overflow or underflow | ||
return -1LL; | ||
}; | ||
if (endptr == id_str) { | ||
// No digits found in the string | ||
return -1LL; | ||
} | ||
if (id < 0) { | ||
// Valid UIDs and GIDs are positive integers | ||
return -1LL; | ||
} | ||
|
||
return id; | ||
} | ||
|
||
// Modify a passwd struct using values from environment variables, if present | ||
struct passwd * | ||
shimpw(struct passwd *pw) | ||
{ | ||
if (pw) { | ||
char *user = getenv("SHIM_USER"); | ||
char *gecos = getenv("SHIM_GECOS"); | ||
char *home = getenv("SHIM_HOME"); | ||
char *shell = getenv("SHIM_SHELL"); | ||
|
||
char *uid_str = getenv("SHIM_UID"); | ||
intmax_t pw_uid = -1; | ||
char *gid_str = getenv("SHIM_GID"); | ||
intmax_t pw_gid = -1; | ||
|
||
// Simple char* assignments | ||
if (user) { pw->pw_name = user; } | ||
if (gecos) { pw->pw_gecos = gecos; } | ||
if (home) { pw->pw_dir = home; } | ||
if (shell) { pw->pw_shell = shell; } | ||
|
||
// Assignments needing char* -> uid_t conversion | ||
if (uid_str) { | ||
pw_uid = str_to_id(uid_str); | ||
// The maximum uid_t/gid_t value is not a valid ID, because it's used as a | ||
// return code to communicate an error/unknown UID by some functions | ||
if (pw_uid >= 0 && pw_uid < (~(uid_t)0)) { | ||
pw->pw_uid = (uid_t) pw_uid; | ||
} | ||
} | ||
if (gid_str) { | ||
pw_gid = str_to_id(gid_str); | ||
if (pw_gid >= 0 && pw_gid < (~(gid_t)0)) { | ||
pw->pw_gid = (gid_t) pw_gid; | ||
} | ||
} | ||
} | ||
return pw; | ||
} | ||
|
||
|
||
// Wrappers to get at the functions being shimmed | ||
typedef struct passwd * | ||
(*real_getpwuid_t) (uid_t); | ||
|
||
struct passwd * | ||
real_getpwuid(uid_t uid) | ||
{ | ||
return ((real_getpwuid_t)dlsym(RTLD_NEXT, "getpwuid"))(uid); | ||
} | ||
|
||
typedef struct passwd * | ||
(*real_getpwnam_t) (const char *name); | ||
|
||
struct passwd * | ||
real_getpwnam(const char *name) | ||
{ | ||
return ((real_getpwnam_t)dlsym(RTLD_NEXT, "getpwnam"))(name); | ||
} | ||
|
||
|
||
// The shim functions | ||
struct passwd * | ||
getpwuid(uid_t uid) | ||
{ | ||
struct passwd *pw = real_getpwuid(uid); | ||
return shimpw(pw); | ||
} | ||
struct passwd * | ||
getpwnam(const char *name) | ||
{ | ||
struct passwd *pw = real_getpwnam(name); | ||
return shimpw(pw); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#!/usr/bin/env bash | ||
SHIM=$1 | ||
TEST_STR_BIN=$2 | ||
TEST_ID_BIN=$3 | ||
|
||
RET=0 | ||
NSS_HOME=$(getent passwd $UID | cut -d : -f 6) | ||
NSS_GID=$(getent passwd $UID | cut -d : -f 4) | ||
|
||
echo -n "Testing home directory without shim... " | ||
RESULT_NOSHIM=$($TEST_STR_BIN) | ||
if [ "$RESULT_NOSHIM" != "$NSS_HOME" ]; then | ||
echo "Failed!" | ||
echo "RESULT_NOSHIM ($RESULT_NOSHIM) != NSS_HOME ($NSS_HOME)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
echo -n "Testing home directory with shim but without variable... " | ||
RESULT_SHIM=$(LD_PRELOAD=$SHIM $TEST_STR_BIN) | ||
if [ "$RESULT_SHIM" != "$NSS_HOME" ]; then | ||
echo "Failed!" | ||
echo "RESULT_SHIM ($RESULT_SHIM) != NSS_HOME ($NSS_HOME)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
echo -n "Testing home directory with shim and variable... " | ||
export SHIM_HOME=$PWD | ||
RESULT_SHIM=$(LD_PRELOAD=$SHIM $TEST_STR_BIN) | ||
if [ "$RESULT_SHIM" != "$SHIM_HOME" ]; then | ||
echo "Failed!" | ||
echo "RESULT_SHIM ($RESULT_SHIM) != SHIM_HOME ($SHIM_HOME)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
echo -n "Testing gid without shim... " | ||
RESULT_NOSHIM=$($TEST_ID_BIN) | ||
stat=$? | ||
if [ "$stat" != 0 ]; then | ||
echo "$TEST_ID_BIN" failed to run! | ||
fi | ||
if [ "$RESULT_NOSHIM" != "$NSS_GID" ]; then | ||
echo "Failed!" | ||
echo "RESULT_NOSHIM ($RESULT_NOSHIM) != NSS_GID ($NSS_GID)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
echo -n "Testing gid with shim but without variable... " | ||
RESULT_SHIM=$(LD_PRELOAD=$SHIM $TEST_ID_BIN) | ||
stat=$? | ||
if [ "$stat" != 0 ]; then | ||
echo "$TEST_ID_BIN" failed to run! | ||
fi | ||
if [ "$RESULT_SHIM" != "$NSS_GID" ]; then | ||
echo "Failed!" | ||
echo "RESULT_SHIM ($RESULT_SHIM) != NSS_GID ($NSS_GID)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
echo $USER | ||
echo -n "Testing gid with shim and variable... " | ||
export SHIM_GID=54201 | ||
RESULT_SHIM=$(LD_PRELOAD=$SHIM $TEST_ID_BIN) | ||
stat=$? | ||
if [ "$stat" != 0 ]; then | ||
echo "$TEST_ID_BIN" failed to run! | ||
fi | ||
if [ "$RESULT_SHIM" != "$SHIM_GID" ]; then | ||
echo "Failed!" | ||
echo "RESULT_SHIM ($RESULT_SHIM) != SHIM_GID ($SHIM_GID)" | ||
RET=1 | ||
else | ||
echo "OK" | ||
fi | ||
|
||
exit $RET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
#include <sys/types.h> | ||
#include <pwd.h> | ||
|
||
int main (int argc, const char *argv[]) { | ||
const uid_t uid = getuid(); | ||
struct passwd *pw_uid = getpwuid(uid); | ||
const char *name = pw_uid->pw_name; | ||
struct passwd *pw_nam = getpwnam(name); | ||
if (pw_uid->pw_gid == pw_nam->pw_gid) { | ||
printf("%lu\n", (unsigned long int) pw_uid->pw_gid); | ||
return EXIT_SUCCESS; | ||
} else { | ||
printf("%s\n", "Returns from getpwuid and getpwnam did not match!"); | ||
printf("%s: %lu\n", "getpwuid", (unsigned long int) pw_uid->pw_gid); | ||
printf("%s: %lu\n", "getpwnam", (unsigned long int) pw_nam->pw_gid); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
#include <sys/types.h> | ||
#include <pwd.h> | ||
|
||
int main (int argc, const char *argv[]) { | ||
const uid_t uid = getuid(); | ||
struct passwd *pw_uid = getpwuid(uid); | ||
const char *name = pw_uid->pw_name; | ||
struct passwd *pw_nam = getpwnam(name); | ||
if (strcmp(pw_uid->pw_dir,pw_nam->pw_dir) == 0) { | ||
printf("%s\n", pw_uid->pw_dir); | ||
return EXIT_SUCCESS; | ||
} else { | ||
printf("%s\n", "Returns from getpwuid and getpwnam did not match!"); | ||
printf("%s: %s\n", "getpwuid", pw_uid->pw_dir); | ||
printf("%s: %s\n", "getpwnam", pw_nam->pw_dir); | ||
return EXIT_FAILURE; | ||
} | ||
} |