/* * libnss_toes - NSS module that resolves unknown usernames to a shared account. * * Any username not found in /etc/passwd gets mapped to a toes-guest entry * with home=/home/toes and shell=/usr/local/bin/toes. * * Build: * gcc -shared -o libnss_toes.so.2 libnss_toes.c -fPIC * * Install: * cp libnss_toes.so.2 /lib/ * # Add "toes" to passwd line in /etc/nsswitch.conf */ #include #include #include #include #define GUEST_UID 65534 #define GUEST_GID 65534 #define GUEST_HOME "/home/toes" #define GUEST_SHELL "/usr/local/bin/toes" #define GUEST_GECOS "Toes Guest" static const char *skip_users[] = { "root", "toes", "nobody", "daemon", "bin", "sys", "sync", "games", "man", "lp", "mail", "news", "uucp", "proxy", "www-data", "backup", "list", "irc", "gnats", "systemd-network", "systemd-resolve", "messagebus", "sshd", "_apt", NULL }; static int should_skip(const char *name) { for (const char **p = skip_users; *p; p++) { if (strcmp(name, *p) == 0) return 1; } return 0; } static enum nss_status fill_passwd(const char *name, struct passwd *pw, char *buf, size_t buflen, int *errnop) { size_t namelen = strlen(name) + 1; size_t gecoslen = strlen(GUEST_GECOS) + 1; size_t homelen = strlen(GUEST_HOME) + 1; size_t shelllen = strlen(GUEST_SHELL) + 1; size_t needed = namelen + gecoslen + homelen + shelllen + 1; /* +1 for pw_passwd "" */ if (buflen < needed) { *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } char *ptr = buf; pw->pw_name = ptr; memcpy(ptr, name, namelen); ptr += namelen; pw->pw_passwd = ptr; *ptr++ = '\0'; pw->pw_uid = GUEST_UID; pw->pw_gid = GUEST_GID; pw->pw_gecos = ptr; memcpy(ptr, GUEST_GECOS, gecoslen); ptr += gecoslen; pw->pw_dir = ptr; memcpy(ptr, GUEST_HOME, homelen); ptr += homelen; pw->pw_shell = ptr; memcpy(ptr, GUEST_SHELL, shelllen); return NSS_STATUS_SUCCESS; } enum nss_status _nss_toes_getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t buflen, int *errnop) { if (!name || !*name || should_skip(name)) { return NSS_STATUS_NOTFOUND; } return fill_passwd(name, pw, buf, buflen, errnop); }