88 lines
2.3 KiB
C
88 lines
2.3 KiB
C
/*
|
|
* 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 <nss.h>
|
|
#include <pwd.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#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);
|
|
}
|