Skip to content

Commit

Permalink
Added project to git repo.
Browse files Browse the repository at this point in the history
  • Loading branch information
Shados committed Dec 1, 2018
0 parents commit ca2e537
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/**
result
26 changes: 26 additions & 0 deletions CMakeLists.txt
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()
14 changes: 14 additions & 0 deletions default.nix
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;
}
3 changes: 3 additions & 0 deletions package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{ pkgs ? import <nixpkgs> { }
}:
pkgs.callPackage ./default.nix { }
11 changes: 11 additions & 0 deletions shell.nix
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
];
}
112 changes: 112 additions & 0 deletions src/getpw.c
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);
}
85 changes: 85 additions & 0 deletions tests/runner.sh
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
23 changes: 23 additions & 0 deletions tests/test-id.c
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;
}
}

22 changes: 22 additions & 0 deletions tests/test-string.c
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;
}
}

0 comments on commit ca2e537

Please sign in to comment.