NSS_WRAPPER(1)

✨ nss_wrapper(1) ✨

okay bestie, gather round, because today we're talking about nss_wrapper β€” a wrapper for the user, group and hosts NSS API πŸ’…. she's a little LD_PRELOAD gremlin and she's about to change your whole testing life, no cap.


🌸 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

that's the whole vibe. you prepend some env vars, you run your app, and suddenly the NSS layer is living in a fantasy world that you control πŸ¦‹


πŸ’– DESCRIPTION πŸ’–

so here's the situation. there are projects out there that ship daemons which need to be able to create, modify and delete Unix users. or they just switch user ids to go interact with the system β€” think a user space file server, iconic behavior honestly. and to be able to test that, you need the privilege to modify the passwd and groups file 😭 which is, like, a lot to ask.

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. your test, your rules, your little fake files, periodt ✨

and 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. cute, right?

  • Provides information for user and group accounts. πŸ‘‘
  • Network name resolution using a hosts file. 🌈
  • Loading and testing of NSS modules. 🧚

😭 LIMITATIONS 😭

not everything is sunshine and rainbows, bestie. 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. and setgroups() is wrapped by uid_wrapper.

so yeah β€” if you forget uid_wrapper, some things just silently do the not-working thing. vibe check your LD_PRELOAD, fr fr πŸ’€

πŸŽ€ 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 we support is:

name:password:UID:GID:GECOS:directory:shell

The format of the group file we support is:

group_name:password:GID:user_list

They are also described in man passwd.5 and man group.5 on Linux. You can fill these files with made up accounts β€” go feral, invent whoever you want πŸ’œ 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 environment, 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

main character hostname energy, honestly 🫢

🌟 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=<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

🌟 NSS_WRAPPER_DISABLE_DEEPBIND

This allows you to disable deep binding in nss_wrapper. This is useful for running valgrind tools or sanitizers like (address, undefined, thread). πŸ”₯


πŸ¦‹ 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

look at that. bob exists now. bob has always existed. bob is real and you can't tell me otherwise 😌✨


πŸ‘‘ AUTHOR πŸ‘‘

Samba Team


and that's the whole page, bestie πŸŽ€ this lil manual is NSS_WRAPPER(1) and it's dated 2024-07-05, brought to you by the Samba Team β€” go forth and fake some users, you absolute icon πŸ’…πŸ«ΆπŸŒŸ