#include <errno.h> #include <nss.h> #include <pthread.h> #include <string.h> #define COPY_IF_ROOM(s) \ ({ size_t len_ = strlen (s) + 1; \ char *start_ = cp; \ buflen - (cp - buffer) < len_ \ ? NULL \ : (cp = mempcpy (cp, s, len_), start_); }) /* Password handling. */ #include <pwd.h> static struct passwd pwd_data[] = { #define PWD(u) \ { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \ .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \ .pw_shell = (char *) "*" } PWD (100), PWD (30), PWD (200), PWD (60), PWD (20000) }; #define npwd_data (sizeof (pwd_data) / sizeof (pwd_data[0])) static size_t pwd_iter; #define CURPWD pwd_data[pwd_iter] static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER; enum nss_status _nss_test1_setpwent (int stayopen) { pwd_iter = 0; return NSS_STATUS_SUCCESS; } enum nss_status _nss_test1_endpwent (void) { return NSS_STATUS_SUCCESS; } enum nss_status _nss_test1_getpwent_r (struct passwd *result, char *buffer, size_t buflen, int *errnop) { char *cp = buffer; int res = NSS_STATUS_SUCCESS; pthread_mutex_lock (&pwd_lock); if (pwd_iter >= npwd_data) res = NSS_STATUS_NOTFOUND; else { result->pw_name = COPY_IF_ROOM (CURPWD.pw_name); result->pw_passwd = COPY_IF_ROOM (CURPWD.pw_passwd); result->pw_uid = CURPWD.pw_uid; result->pw_gid = CURPWD.pw_gid; result->pw_gecos = COPY_IF_ROOM (CURPWD.pw_gecos); result->pw_dir = COPY_IF_ROOM (CURPWD.pw_dir); result->pw_shell = COPY_IF_ROOM (CURPWD.pw_shell); if (result->pw_name == NULL || result->pw_passwd == NULL || result->pw_gecos == NULL || result->pw_dir == NULL || result->pw_shell == NULL) { *errnop = ERANGE; res = NSS_STATUS_TRYAGAIN; } ++pwd_iter; } pthread_mutex_unlock (&pwd_lock); return res; } enum nss_status _nss_test1_getpwuid_r (uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { for (size_t idx = 0; idx < npwd_data; ++idx) if (pwd_data[idx].pw_uid == uid) { char *cp = buffer; int res = NSS_STATUS_SUCCESS; result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); result->pw_uid = pwd_data[idx].pw_uid; result->pw_gid = pwd_data[idx].pw_gid; result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); if (result->pw_name == NULL || result->pw_passwd == NULL || result->pw_gecos == NULL || result->pw_dir == NULL || result->pw_shell == NULL) { *errnop = ERANGE; res = NSS_STATUS_TRYAGAIN; } return res; } return NSS_STATUS_NOTFOUND; } enum nss_status _nss_test1_getpwnam_r (const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop) { for (size_t idx = 0; idx < npwd_data; ++idx) if (strcmp (pwd_data[idx].pw_name, name) == 0) { char *cp = buffer; int res = NSS_STATUS_SUCCESS; result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); result->pw_uid = pwd_data[idx].pw_uid; result->pw_gid = pwd_data[idx].pw_gid; result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); if (result->pw_name == NULL || result->pw_passwd == NULL || result->pw_gecos == NULL || result->pw_dir == NULL || result->pw_shell == NULL) { *errnop = ERANGE; res = NSS_STATUS_TRYAGAIN; } return res; } return NSS_STATUS_NOTFOUND; }