From a21ee75e549a14235a8d55645d2af23d547d1553 Mon Sep 17 00:00:00 2001 From: Liam Hopkins Date: Mon, 10 Jun 2019 14:21:58 -0700 Subject: refactor Makefile (#787) --- packages/google-compute-engine-oslogin/Makefile | 211 ++++------ .../libnss_cache_oslogin/compat/getpwent_r.c | 87 ---- .../libnss_cache_oslogin/nss_cache_oslogin.c | 458 --------------------- .../libnss_cache_oslogin/nss_cache_oslogin.h | 65 --- .../nss_module/compat/getpwent_r.c | 87 ++++ .../nss_module/nss_cache_oslogin.c | 458 +++++++++++++++++++++ .../nss_module/nss_cache_oslogin.h | 65 +++ .../packaging/debian/links | 2 - .../packaging/debian/manpages | 2 - .../packaging/debian/rules | 4 +- .../packaging/google-compute-engine-oslogin.spec | 20 +- .../packaging/setup_deb.sh | 2 +- 12 files changed, 693 insertions(+), 768 deletions(-) delete mode 100644 packages/google-compute-engine-oslogin/libnss_cache_oslogin/compat/getpwent_r.c delete mode 100644 packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.c delete mode 100644 packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.h create mode 100644 packages/google-compute-engine-oslogin/nss_module/compat/getpwent_r.c create mode 100644 packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.c create mode 100644 packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.h delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/links delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/manpages diff --git a/packages/google-compute-engine-oslogin/Makefile b/packages/google-compute-engine-oslogin/Makefile index 1d7295e..67400cd 100644 --- a/packages/google-compute-engine-oslogin/Makefile +++ b/packages/google-compute-engine-oslogin/Makefile @@ -1,158 +1,89 @@ SHELL = /bin/sh -BASENAME = oslogin -NAME = google-compute-engine-$(BASENAME) -MAJOR = 1 -MINOR = 5 -REVISION = 3 - -LIBNSS_CACHE_OSLOGIN = libnss_cache_$(BASENAME) -LIBNSS_CACHE_OSLOGIN_NAME = libnss_cache_$(NAME)-$(MAJOR).$(MINOR).$(REVISION).so -LIBNSS_CACHE_OSLOGIN_SONAME = $(LIBNSS_CACHE_OSLOGIN).so.2 -NSS_LIBRARY_NAME = libnss_$(NAME)-$(MAJOR).$(MINOR).$(REVISION).so -NSS_LIBRARY_SONAME = libnss_$(BASENAME).so.2 -NSS_INSTALL_PATH = /lib -PAM_INSTALL_PATH = /lib/security -AUTHKEYS_INSTALL_PATH = /usr/bin - -JSON_INCLUDE_PATH = /usr/include/json-c -INCLUDE_FLAGS = -I$(JSON_INCLUDE_PATH) - -CXX ?= g++ -CXXFLAGS += -fPIC# -Wall -CC ?= gcc -PAMFLAGS = $(LDFLAGS) $(INCLUDE_FLAGS) -shared -NSSFLAGS = $(LDFLAGS) $(INCLUDE_FLAGS) -shared -Wl,-soname,$(NSS_LIBRARY_SONAME) -LIBNSSFLAGS = $(LDFLAGS) -Wall -Wstrict-prototypes -fPIC -g -LIBNSS_SO_FLAGS = $(LIBNSSFLAGS) -shared -Wl,-soname,$(LIBNSS_CACHE_OSLOGIN_SONAME) - -# UTILS -UTILS_DIR = utils -UTILS_SRC = $(UTILS_DIR)/$(BASENAME)_utils.cc -UTILS = $(UTILS_DIR)/$(BASENAME)_utils.o - -# AUTHORIZED KEYS -AUTHKEYS_DIR = authorized_keys -AUTHKEYS_SRC = $(AUTHKEYS_DIR)/authorized_keys.cc -AUTHKEYS_BIN = google_authorized_keys - -# NSS -NSS = nss_$(BASENAME) -NSS_DIR = nss_module -NSS_SRC = $(NSS_DIR)/$(NSS).cc - -# NSS CACHE -NSS_CACHE = nss_cache -NSS_CACHE_DIR = nss_cache -NSS_CACHE_BIN = google_$(BASENAME)_nss_cache -NSS_CACHE_SRC = $(NSS_CACHE_DIR)/$(NSS_CACHE).cc - -# LIBNSS OSLOGIN CACHE -LIBNSS_CACHE_OSLOGIN_DIR = $(LIBNSS_CACHE_OSLOGIN) -LIBNSS_CACHE = nss_cache_$(BASENAME) -LIBNSS_CACHE_SRC = $(LIBNSS_CACHE_OSLOGIN_DIR)/$(LIBNSS_CACHE).c -LIBNSS_CACHE_OBJ = $(LIBNSS_CACHE_OSLOGIN_DIR)/$(LIBNSS_CACHE).o -LIBNSS_COMPAT = compat/getpwent_r -LIBNSS_COMPAT_SRC = $(LIBNSS_CACHE_OSLOGIN_DIR)/$(LIBNSS_COMPAT).c -LIBNSS_COMPAT_OBJ = $(LIBNSS_CACHE_OSLOGIN_DIR)/$(LIBNSS_COMPAT).o - -# PAM -PAM = pam_$(BASENAME) -PAM_DIR = pam_module -PAM_ADMIN = $(PAM)_admin -PAM_ADMIN_SRC = $(PAM_DIR)/$(PAM_ADMIN).cc -PAM_ADMIN_OBJ = $(PAM_DIR)/$(PAM_ADMIN).o -PAM_ADMIN_MOD = $(PAM_ADMIN).so -PAM_LOGIN = $(PAM)_login -PAM_LOGIN_SRC = $(PAM_DIR)/$(PAM_LOGIN).cc -PAM_LOGIN_OBJ = $(PAM_DIR)/$(PAM_LOGIN).o -PAM_LOGIN_MOD = $(PAM_LOGIN).so - -# HELPER SCRIPTS -BIN_DIR = bin -OSLOGIN_HELPER = $(BIN_DIR)/google_oslogin_control -BIN_INSTALL_PATH = /usr/bin - -# SELINUX POLICY -INSTALL_SELINUX = -POLICY_DIR = policy -SELINUX_INSTALL_NAME = oslogin.pp -SELINUX_MODULE = $(POLICY_DIR)/$(SELINUX_INSTALL_NAME) -SELINUX_INSTALL_PATH = /usr/share/selinux/packages - -LIBS = -lcurl -ljson-c -PAM_LIBS = -lpam $(LIBS) +VERSION = 1.5.3 -ifdef INSTALL_SELINUX -all: $(NSS) $(NSS_CACHE_BIN) $(LIBNSS_CACHE_OSLOGIN_NAME) $(PAM) $(AUTHKEYS_BIN) -else -all: $(NSS) $(NSS_CACHE_BIN) $(LIBNSS_CACHE_OSLOGIN_NAME) $(PAM) $(AUTHKEYS_BIN) -endif +CPPFLAGS = -I/usr/include/json-c +CXXFLAGS = -fPIC -Wall -g +CFLAGS = $(CXXFLAGS) -Wstrict-prototypes -$(NSS): $(NSS_LIBRARY_SOURCE) $(UTILS) - $(CXX) $(CXXFLAGS) $(NSSFLAGS) -o $(NSS_LIBRARY_NAME) \ - $(NSS_SRC) $(UTILS) $(LIBS) +LDFLAGS = -shared -Wl,-soname,$(SONAME) +LDLIBS = -lcurl -ljson-c +PAMLIBS = -lpam $(LDLIBS) -$(NSS_CACHE_BIN): $(NSS_CACHE_SRC) $(UTILS_SRC) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(INCLUDE_FLAGS) -o $(NSS_CACHE_BIN) $(NSS_CACHE_SRC) $(UTILS_SRC) $(LIBS) +# Paths which should be overrideable. -$(LIBNSS_CACHE_OSLOGIN_NAME): $(LIBNSS_CACHE_OBJ) $(LIBNSS_COMPAT_OBJ) - $(CXX) $(LIBNSS_SO_FLAGS) -o $(LIBNSS_CACHE_OSLOGIN_NAME) $(LIBNSS_CACHE_OBJ) $(LIBNSS_COMPAT_OBJ) +PREFIX = /usr +LIBDIR = $(PREFIX)/lib +BINDIR = $(PREFIX)/bin +PAMDIR = $(LIBDIR)/security +MANDIR = /usr/share/man -$(LIBNSS_CACHE_OBJ): $(LIBNSS_CACHE_SRC) - $(CC) $(LIBNSSFLAGS) -c -o $(LIBNSS_CACHE_OBJ) $(LIBNSS_CACHE_SRC) +NSS_OSLOGIN_SONAME = libnss_oslogin.so.2 +NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2 -$(LIBNSS_COMPAT_OBJ): $(LIBNSS_COMPAT_SRC) - $(CC) $(LIBNSSFLAGS) -c -o $(LIBNSS_COMPAT_OBJ) $(LIBNSS_COMPAT_SRC) +NSS_OSLOGIN = nss_module/libnss_oslogin-$(VERSION).so +NSS_CACHE_OSLOGIN = nss_module/libnss_cache_oslogin-$(VERSION).so -$(PAM): $(PAM_ADMIN_MOD) $(PAM_LOGIN_MOD) +PAM_LOGIN = pam_module/pam_oslogin_login.so +PAM_ADMIN = pam_module/pam_oslogin_admin.so -$(PAM_LOGIN_MOD): $(PAM_LOGIN_OBJ) $(UTILS) - $(CXX) $(PAMFLAGS) -o $(PAM_LOGIN_MOD) $(PAM_LOGIN_OBJ) $(UTILS) $(PAM_LIBS) +BINARIES = google_oslogin_nss_cache google_authorized_keys bin/google_oslogin_control -$(PAM_ADMIN_MOD): $(PAM_ADMIN_OBJ) $(UTILS) - $(CXX) $(PAMFLAGS) -o $(PAM_ADMIN_MOD) $(PAM_ADMIN_OBJ) $(UTILS) $(PAM_LIBS) +all : $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(PAM_ADMIN) $(BINARIES) -$(PAM_LOGIN_OBJ): $(PAM_LOGIN_SRC) - $(CXX) $(CXXFLAGS) -c $(PAM_LOGIN_SRC) -o $(PAM_LOGIN_OBJ) +clean : + rm -f */*.o */*.so google_oslogin_nss_cache google_authorized_keys -$(PAM_ADMIN_OBJ): $(PAM_ADMIN_SRC) - $(CXX) $(CXXFLAGS) -c $(PAM_ADMIN_SRC) -o $(PAM_ADMIN_OBJ) +.PHONY : all clean install -$(AUTHKEYS_BIN): $(AUTHKEYS_SRC) $(UTILS_SRC) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(INCLUDE_FLAGS) -o $(AUTHKEYS_BIN) $(AUTHKEYS_SRC) $(UTILS_SRC) $(LIBS) +# NSS modules. -$(UTILS): $(UTILS_SRC) - $(CXX) $(CXXFLAGS) $(INCLUDE_FLAGS) -c $(UTILS_SRC) -o $(UTILS) +$(NSS_OSLOGIN) : SONAME = $(NSS_OSLOGIN_SONAME) +$(NSS_OSLOGIN) : nss_module/nss_oslogin.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) -install: $(NSS_LIBRARY_NAME) $(LIBNSS_OSLOGIN_CACHE_NAME) $(PAM_ADMIN_MOD) $(PAM_LOGIN_MOD) $(AUTHKEYS_BIN) $(NSS_CACHE_BIN) - mkdir -p $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH) - mkdir -p $(DESTDIR)$(PREFIX)/$(PAM_INSTALL_PATH) - mkdir -p $(DESTDIR)$(PREFIX)/$(AUTHKEYS_INSTALL_PATH) - mkdir -p $(DESTDIR)$(PREFIX)/$(BIN_INSTALL_PATH) - install -m 0644 $(LIBNSS_CACHE_OSLOGIN_NAME) $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH) - install -m 0644 $(NSS_LIBRARY_NAME) $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH) - install -m 0644 $(PAM_ADMIN_MOD) $(PAM_LOGIN_MOD) $(DESTDIR)$(PREFIX)/$(PAM_INSTALL_PATH) - install -m 0755 $(AUTHKEYS_BIN) $(DESTDIR)$(PREFIX)/$(AUTHKEYS_INSTALL_PATH) - install -m 0755 $(OSLOGIN_HELPER) $(DESTDIR)$(PREFIX)/$(BIN_INSTALL_PATH) - install -m 0755 $(NSS_CACHE_BIN) $(DESTDIR)$(PREFIX)/$(BIN_INSTALL_PATH) -ifdef MAKE_LINKS - ln -sf $(LIBNSS_CACHE_OSLOGIN_NAME) $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH)/$(LIBNSS_CACHE_OSLOGIN_SONAME) - ln -sf $(NSS_LIBRARY_NAME) $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH)/$(NSS_LIBRARY_SONAME) -endif -ifdef INSTALL_SELINUX - mkdir -p $(DESTDIR)$(PREFIX)/$(SELINUX_INSTALL_PATH) - install -T -m 0644 $(SELINUX_MODULE) $(DESTDIR)$(PREFIX)/$(SELINUX_INSTALL_PATH)/$(SELINUX_INSTALL_NAME) -endif +$(NSS_CACHE_OSLOGIN) : SONAME = $(NSS_CACHE_OSLOGIN_SONAME) +$(NSS_CACHE_OSLOGIN) : nss_module/nss_cache_oslogin.o nss_module/compat/getpwent_r.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +# PAM modules + +$(PAM_LOGIN) : pam_module/pam_oslogin_login.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS) + +$(PAM_ADMIN) : pam_module/pam_oslogin_admin.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS) -uninstall: - rm -f $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH)/$(LIBNSS_CACHE_OSLOGIN_NAME) - rm -f $(DESTDIR)$(PREFIX)/$(NSS_INSTALL_PATH)/$(NSS_LIBRARY_NAME) - rm -f $(DESTDIR)$(PREFIX)/$(PAM_INSTALL_PATH)/$(PAM_ADMIN_MOD) - rm -f $(DESTDIR)$(PREFIX)/$(PAM_INSTALL_PATH)/$(PAM_LOGIN_MOD) - rm -f $(DESTDIR)$(PREFIX)/$(AUTHKEYS_INSTALL_PATH)/$(AUTHKEYS_BIN) - rm -f $(DESTDIR)$(PREFIX)/$(BIN_INSTALL_PATH)/$(OSLOGIN_HELPER) - rm -f $(DESTDIR)$(PREFIX)/$(BIN_INSTALL_PATH)/$(NSS_CACHE_BIN) -clean: - rm -f $(UTILS) $(NSS_LIBRARY_NAME) $(LIBNSS_CACHE_OSLOGIN_NAME) $(LIBNSS_CACHE_OBJ) $(LIBNSS_COMPAT_OBJ) $(PAM_ADMIN_OBJ) $(PAM_ADMIN_MOD) $(PAM_LOGIN_OBJ) $(PAM_LOGIN_MOD) $(AUTHKEYS_BIN) $(NSS_CACHE_BIN) +# Utilities. +google_authorized_keys : authorized_keys/authorized_keys.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) + +google_oslogin_nss_cache: nss_cache/nss_cache.o utils/oslogin_utils.o + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) + +# Define these to add dependency on header files. + +utils/oslogin_utils.o : utils/oslogin_utils.cc utils/oslogin_utils.h + +nss_module/nss_cache_oslogin.o : nss_module/nss_cache_oslogin.c nss_module/nss_cache_oslogin.h + +install: all + install -d $(DESTDIR)$(LIBDIR) + install -d $(DESTDIR)$(PAMDIR) + install -d $(DESTDIR)$(BINDIR) + install -d $(DESTDIR)$(MANDIR)/man8 + install -m 0644 -t $(DESTDIR)$(LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) + install -m 0644 -t $(DESTDIR)$(PAMDIR) $(PAM_ADMIN) $(PAM_LOGIN) + install -m 0755 -t $(DESTDIR)$(BINDIR) $(BINARIES) + install -m 0644 -t $(DESTDIR)$(MANDIR)/man8 nss_module/nss-oslogin.8 nss_module/nss-cache-oslogin.8 + gzip -9 $(DESTDIR)$(MANDIR)/man8/nss-oslogin.8 + gzip -9 $(DESTDIR)$(MANDIR)/man8/nss-cache-oslogin.8 + ln -sf nss-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz + ln -sf nss-cache-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz + ln -sf $(notdir $(NSS_OSLOGIN)) $(DESTDIR)$(LIBDIR)/$(NSS_OSLOGIN_SONAME) + ln -sf $(notdir $(NSS_CACHE_OSLOGIN)) $(DESTDIR)$(LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME) +ifdef INSTALL_SELINUX + install -d $(DESTDIR)/usr/share/selinux/packages + install -m 0644 -t $(DESTDIR)/usr/share/selinux/packages policy/oslogin.pp +endif diff --git a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/compat/getpwent_r.c b/packages/google-compute-engine-oslogin/libnss_cache_oslogin/compat/getpwent_r.c deleted file mode 100644 index b1be6fc..0000000 --- a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/compat/getpwent_r.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ---------------------------------------------------------------------- - * Copyright © 2005-2014 Rich Felker, et al. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * ---------------------------------------------------------------------- - * - * Adapted from http://www.musl-libc.org/ for libnss-cache - * Copyright © 2015 Kevin Bowling - */ - -#include - -#ifdef BSD - -#include -#include -#include -#include -#include - -static unsigned atou(char **s) -{ - unsigned x; - for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0'); - return x; -} - -int fgetpwent_r(FILE *f, struct passwd *pw, char *line, size_t size, struct passwd **res) -{ - char *s; - int rv = 0; - for (;;) { - line[size-1] = '\xff'; - if ( (fgets(line, size, f) == NULL) || ferror(f) || line[size-1] != '\xff' ) { - rv = (line[size-1] != '\xff') ? ERANGE : ENOENT; - line = 0; - pw = 0; - break; - } - line[strcspn(line, "\n")] = 0; - - s = line; - pw->pw_name = s++; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; pw->pw_passwd = s; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; pw->pw_uid = atou(&s); - if (*s != ':') continue; - - *s++ = 0; pw->pw_gid = atou(&s); - if (*s != ':') continue; - - *s++ = 0; pw->pw_gecos = s; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; pw->pw_dir = s; - if (!(s = strchr(s, ':'))) continue; - - *s++ = 0; pw->pw_shell = s; - break; - } - *res = pw; - if (rv) errno = rv; - return rv; -} - -#endif // ifdef BSD diff --git a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.c b/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.c deleted file mode 100644 index 28f0e0d..0000000 --- a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.c +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// An NSS module which adds supports for file /etc/oslogin_passwd.cache - -#include "nss_cache_oslogin.h" -#include "../compat.h" - -#include - -// Locking implementation: use pthreads. -#include -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -#define NSS_CACHE_OSLOGIN_LOCK() \ - do { \ - pthread_mutex_lock(&mutex); \ - } while (0) -#define NSS_CACHE_OSLOGIN_UNLOCK() \ - do { \ - pthread_mutex_unlock(&mutex); \ - } while (0) - -static FILE *p_file = NULL; -static char p_filename[NSS_CACHE_OSLOGIN_PATH_LENGTH] = NSS_CACHE_OSLOGIN_PATH; -#ifdef BSD -extern int fgetpwent_r(FILE *, struct passwd *, char *, size_t, - struct passwd **); -#endif // ifdef BSD - -/* Common return code routine for all *ent_r_locked functions. - * We need to return TRYAGAIN if the underlying files guy raises ERANGE, - * so that our caller knows to try again with a bigger buffer. - */ - -static inline enum nss_status _nss_cache_oslogin_ent_bad_return_code( - int errnoval) { - enum nss_status ret; - - switch (errnoval) { - case ERANGE: - DEBUG("ERANGE: Try again with a bigger buffer\n"); - ret = NSS_STATUS_TRYAGAIN; - break; - case ENOENT: - default: - DEBUG("ENOENT or default case: Not found\n"); - ret = NSS_STATUS_NOTFOUND; - }; - return ret; -} - -// -// Binary search routines below here -// - -int _nss_cache_oslogin_bsearch2_compare(const void *key, const void *value) { - struct nss_cache_oslogin_args *args = (struct nss_cache_oslogin_args *)key; - const char *value_text = (const char *)value; - - // Using strcmp as the generation of the index sorts without - // locale awareness. - return strcmp(args->lookup_key, value_text); -} - -enum nss_status _nss_cache_oslogin_bsearch2(struct nss_cache_oslogin_args *args, - int *errnop) { - enum nss_cache_oslogin_match (*lookup)( - FILE *, struct nss_cache_oslogin_args *) = args->lookup_function; - FILE *file = NULL; - FILE *system_file_stream = NULL; - struct stat system_file; - struct stat sorted_file; - enum nss_status ret = 100; - long offset = 0; - void *mapped_data = NULL; - - file = fopen(args->sorted_filename, "r"); - if (file == NULL) { - DEBUG("error opening %s\n", args->sorted_filename); - return NSS_STATUS_UNAVAIL; - } - - // if the sorted file is older than the system file, do not risk stale - // data and abort - // TODO(vasilios): should be a compile or runtime option - if (stat(args->system_filename, &system_file) != 0) { - DEBUG("failed to stat %s\n", args->system_filename); - fclose(file); - return NSS_STATUS_UNAVAIL; - } - if (fstat(fileno(file), &sorted_file) != 0) { - DEBUG("failed to stat %s\n", args->sorted_filename); - fclose(file); - return NSS_STATUS_UNAVAIL; - } - if (difftime(system_file.st_mtime, sorted_file.st_mtime) > 0) { - DEBUG("%s may be stale, aborting lookup\n", args->sorted_filename); - fclose(file); - return NSS_STATUS_UNAVAIL; - } - - mapped_data = - mmap(NULL, sorted_file.st_size, PROT_READ, MAP_PRIVATE, fileno(file), 0); - if (mapped_data == MAP_FAILED) { - DEBUG("mmap failed\n"); - fclose(file); - return NSS_STATUS_UNAVAIL; - } - - const char *data = (const char *)mapped_data; - while (*data != '\n') { - ++data; - } - long entry_size = data - (const char *)mapped_data + 1; - long entry_count = sorted_file.st_size / entry_size; - - void *entry = bsearch(args, mapped_data, entry_count, entry_size, - &_nss_cache_oslogin_bsearch2_compare); - if (entry != NULL) { - const char *entry_text = entry; - sscanf(entry_text + strlen(entry_text) + 1, "%ld", &offset); - } - - if (munmap(mapped_data, sorted_file.st_size) == -1) { - DEBUG("munmap failed\n"); - } - fclose(file); - - if (entry == NULL) { - return NSS_STATUS_NOTFOUND; - } - - system_file_stream = fopen(args->system_filename, "r"); - if (system_file_stream == NULL) { - DEBUG("error opening %s\n", args->system_filename); - return NSS_STATUS_UNAVAIL; - } - - if (fseek(system_file_stream, offset, SEEK_SET) != 0) { - DEBUG("fseek fail\n"); - return NSS_STATUS_UNAVAIL; - } - - switch (lookup(system_file_stream, args)) { - case NSS_CACHE_OSLOGIN_EXACT: - ret = NSS_STATUS_SUCCESS; - break; - case NSS_CACHE_OSLOGIN_ERROR: - if (errno == ERANGE) { - // let the caller retry - *errnop = errno; - ret = _nss_cache_oslogin_ent_bad_return_code(*errnop); - } - break; - default: - ret = NSS_STATUS_UNAVAIL; - break; - } - - fclose(system_file_stream); - return ret; -} - -// -// Routines for passwd map defined below here -// - -// _nss_cache_oslogin_setpwent_path() -// Helper function for testing - -extern char *_nss_cache_oslogin_setpwent_path(const char *path) { - DEBUG("%s %s\n", "Setting p_filename to", path); - return strncpy(p_filename, path, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); -} - -// _nss_cache_oslogin_pwuid_wrap() -// Internal wrapper for binary searches, using uid-specific calls. - -static enum nss_cache_oslogin_match _nss_cache_oslogin_pwuid_wrap( - FILE *file, struct nss_cache_oslogin_args *args) { - struct passwd *result = args->lookup_result; - uid_t *uid = args->lookup_value; - - if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) { - if (result->pw_uid == *uid) { - DEBUG("SUCCESS: found user %d:%s\n", result->pw_uid, result->pw_name); - return NSS_CACHE_OSLOGIN_EXACT; - } - DEBUG("Failed match at uid %d\n", result->pw_uid); - if (result->pw_uid > *uid) { - return NSS_CACHE_OSLOGIN_HIGH; - } else { - return NSS_CACHE_OSLOGIN_LOW; - } - } - - return NSS_CACHE_OSLOGIN_ERROR; -} - -// _nss_cache_oslogin_pwnam_wrap() -// Internal wrapper for binary searches, using username-specific calls. - -static enum nss_cache_oslogin_match _nss_cache_oslogin_pwnam_wrap( - FILE *file, struct nss_cache_oslogin_args *args) { - struct passwd *result = args->lookup_result; - char *name = args->lookup_value; - int ret; - - if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) { - ret = strcoll(result->pw_name, name); - if (ret == 0) { - DEBUG("SUCCESS: found user %s\n", result->pw_name); - return NSS_CACHE_OSLOGIN_EXACT; - } - DEBUG("Failed match at name %s\n", result->pw_name); - if (ret > 0) { - return NSS_CACHE_OSLOGIN_HIGH; - } else { - return NSS_CACHE_OSLOGIN_LOW; - } - } - - return NSS_CACHE_OSLOGIN_ERROR; -} - -// _nss_cache_oslogin_setpwent_locked() -// Internal setup routine - -static enum nss_status _nss_cache_oslogin_setpwent_locked(void) { - DEBUG("%s %s\n", "Opening", p_filename); - p_file = fopen(p_filename, "r"); - - if (p_file) { - return NSS_STATUS_SUCCESS; - } else { - return NSS_STATUS_UNAVAIL; - } -} - -// _nss_cache_oslogin_setpwent() -// Called by NSS to open the passwd file -// 'stayopen' parameter is ignored. - -enum nss_status _nss_cache_oslogin_setpwent(int stayopen) { - enum nss_status ret; - NSS_CACHE_OSLOGIN_LOCK(); - ret = _nss_cache_oslogin_setpwent_locked(); - NSS_CACHE_OSLOGIN_UNLOCK(); - return ret; -} - -// _nss_cache_oslogin_endpwent_locked() -// Internal close routine - -static enum nss_status _nss_cache_oslogin_endpwent_locked(void) { - DEBUG("Closing passwd.cache\n"); - if (p_file) { - fclose(p_file); - p_file = NULL; - } - return NSS_STATUS_SUCCESS; -} - -// _nss_cache_oslogin_endpwent() -// Called by NSS to close the passwd file - -enum nss_status _nss_cache_oslogin_endpwent(void) { - enum nss_status ret; - NSS_CACHE_OSLOGIN_LOCK(); - ret = _nss_cache_oslogin_endpwent_locked(); - NSS_CACHE_OSLOGIN_UNLOCK(); - return ret; -} - -// _nss_cache_oslogin_getpwent_r_locked() -// Called internally to return the next entry from the passwd file - -static enum nss_status _nss_cache_oslogin_getpwent_r_locked( - struct passwd *result, char *buffer, size_t buflen, int *errnop) { - enum nss_status ret = NSS_STATUS_SUCCESS; - - if (p_file == NULL) { - DEBUG("p_file == NULL, going to setpwent\n"); - ret = _nss_cache_oslogin_setpwent_locked(); - } - - if (ret == NSS_STATUS_SUCCESS) { - if (fgetpwent_r(p_file, result, buffer, buflen, &result) == 0) { - DEBUG("Returning user %d:%s\n", result->pw_uid, result->pw_name); - } else { - if (errno == ENOENT) { - errno = 0; - } - *errnop = errno; - ret = _nss_cache_oslogin_ent_bad_return_code(*errnop); - } - } - - return ret; -} - -// _nss_cache_oslogin_getpwent_r() -// Called by NSS to look up next entry in passwd file - -enum nss_status _nss_cache_oslogin_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { - enum nss_status ret; - NSS_CACHE_OSLOGIN_LOCK(); - ret = _nss_cache_oslogin_getpwent_r_locked(result, buffer, buflen, errnop); - NSS_CACHE_OSLOGIN_UNLOCK(); - return ret; -} - -// _nss_cache_oslogin_getpwuid_r() -// Find a user account by uid - -enum nss_status _nss_cache_oslogin_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { - char filename[NSS_CACHE_OSLOGIN_PATH_LENGTH]; - struct nss_cache_oslogin_args args; - enum nss_status ret; - - strncpy(filename, p_filename, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); - if (strlen(filename) > NSS_CACHE_OSLOGIN_PATH_LENGTH - 7) { - DEBUG("filename too long\n"); - return NSS_STATUS_UNAVAIL; - } - strncat(filename, ".ixuid", 6); - - args.sorted_filename = filename; - args.system_filename = p_filename; - args.lookup_function = _nss_cache_oslogin_pwuid_wrap; - args.lookup_value = &uid; - args.lookup_result = result; - args.buffer = buffer; - args.buflen = buflen; - char uid_text[11]; - snprintf(uid_text, sizeof(uid_text), "%d", uid); - args.lookup_key = uid_text; - args.lookup_key_length = strlen(uid_text); - - DEBUG("Binary search for uid %d\n", uid); - NSS_CACHE_OSLOGIN_LOCK(); - ret = _nss_cache_oslogin_bsearch2(&args, errnop); - - if (ret == NSS_STATUS_UNAVAIL) { - DEBUG("Binary search failed, falling back to full linear search\n"); - ret = _nss_cache_oslogin_setpwent_locked(); - - if (ret == NSS_STATUS_SUCCESS) { - while ((ret = _nss_cache_oslogin_getpwent_r_locked( - result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) { - if (result->pw_uid == uid) break; - } - } - } - - _nss_cache_oslogin_endpwent_locked(); - NSS_CACHE_OSLOGIN_UNLOCK(); - - return ret; -} - -// _nss_cache_oslogin_getpwnam_r() -// Find a user account by name - -enum nss_status _nss_cache_oslogin_getpwnam_r(const char *name, - struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { - char *pw_name; - char filename[NSS_CACHE_OSLOGIN_PATH_LENGTH]; - struct nss_cache_oslogin_args args; - enum nss_status ret; - - NSS_CACHE_OSLOGIN_LOCK(); - - // name is a const char, we need a non-const copy - pw_name = malloc(strlen(name) + 1); - if (pw_name == NULL) { - DEBUG("malloc error\n"); - return NSS_STATUS_UNAVAIL; - } - strncpy(pw_name, name, strlen(name) + 1); - - strncpy(filename, p_filename, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); - if (strlen(filename) > NSS_CACHE_OSLOGIN_PATH_LENGTH - 8) { - DEBUG("filename too long\n"); - free(pw_name); - return NSS_STATUS_UNAVAIL; - } - strncat(filename, ".ixname", 7); - - args.sorted_filename = filename; - args.system_filename = p_filename; - args.lookup_function = _nss_cache_oslogin_pwnam_wrap; - args.lookup_value = pw_name; - args.lookup_result = result; - args.buffer = buffer; - args.buflen = buflen; - args.lookup_key = pw_name; - args.lookup_key_length = strlen(pw_name); - - DEBUG("Binary search for user %s\n", pw_name); - ret = _nss_cache_oslogin_bsearch2(&args, errnop); - - if (ret == NSS_STATUS_UNAVAIL) { - DEBUG("Binary search failed, falling back to full linear search\n"); - ret = _nss_cache_oslogin_setpwent_locked(); - - if (ret == NSS_STATUS_SUCCESS) { - while ((ret = _nss_cache_oslogin_getpwent_r_locked( - result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) { - if (!strcmp(result->pw_name, name)) break; - } - } - } - - free(pw_name); - _nss_cache_oslogin_endpwent_locked(); - NSS_CACHE_OSLOGIN_UNLOCK(); - - return ret; -} - -NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r); -NSS_METHOD_PROTOTYPE(__nss_compat_setpwent); -NSS_METHOD_PROTOTYPE(__nss_compat_endpwent); - -DECLARE_NSS_METHOD_TABLE(methods, - { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, - (void*)_nss_cache_oslogin_getpwnam_r }, - { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, - (void*)_nss_cache_oslogin_getpwuid_r }, - { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, - (void*)_nss_cache_oslogin_getpwent_r }, - { NSDB_PASSWD, "endpwent", __nss_compat_endpwent, - (void*)_nss_cache_oslogin_endpwent }, - { NSDB_PASSWD, "setpwent", __nss_compat_setpwent, - (void*)_nss_cache_oslogin_setpwent }, -) - -NSS_REGISTER_METHODS(methods) diff --git a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.h b/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.h deleted file mode 100644 index 25c7274..0000000 --- a/packages/google-compute-engine-oslogin/libnss_cache_oslogin/nss_cache_oslogin.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NSS_CACHE_OSLOGIN_H -#define NSS_CACHE_OSLOGIN_H - -#ifdef DEBUG -#undef DEBUG -#define DEBUG(fmt, args...) \ - do { \ - fprintf(stderr, fmt, ##args); \ - } while (0) -#else -#define DEBUG(fmt, ...) \ - do { \ - } while (0) -#endif /* DEBUG */ - -#define NSS_CACHE_OSLOGIN_PATH_LENGTH 255 -extern char *_nss_cache_oslogin_setpwent_path(const char *path); - -enum nss_cache_oslogin_match { - NSS_CACHE_OSLOGIN_EXACT = 0, - NSS_CACHE_OSLOGIN_HIGH = 1, - NSS_CACHE_OSLOGIN_LOW = 2, - NSS_CACHE_OSLOGIN_ERROR = 3, -}; - -struct nss_cache_oslogin_args { - char *system_filename; - char *sorted_filename; - void *lookup_function; - void *lookup_value; - void *lookup_result; - char *buffer; - size_t buflen; - char *lookup_key; - size_t lookup_key_length; -}; - -#endif /* NSS_CACHE_OSLOGIN_H */ diff --git a/packages/google-compute-engine-oslogin/nss_module/compat/getpwent_r.c b/packages/google-compute-engine-oslogin/nss_module/compat/getpwent_r.c new file mode 100644 index 0000000..b1be6fc --- /dev/null +++ b/packages/google-compute-engine-oslogin/nss_module/compat/getpwent_r.c @@ -0,0 +1,87 @@ +/* + * ---------------------------------------------------------------------- + * Copyright © 2005-2014 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ---------------------------------------------------------------------- + * + * Adapted from http://www.musl-libc.org/ for libnss-cache + * Copyright © 2015 Kevin Bowling + */ + +#include + +#ifdef BSD + +#include +#include +#include +#include +#include + +static unsigned atou(char **s) +{ + unsigned x; + for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0'); + return x; +} + +int fgetpwent_r(FILE *f, struct passwd *pw, char *line, size_t size, struct passwd **res) +{ + char *s; + int rv = 0; + for (;;) { + line[size-1] = '\xff'; + if ( (fgets(line, size, f) == NULL) || ferror(f) || line[size-1] != '\xff' ) { + rv = (line[size-1] != '\xff') ? ERANGE : ENOENT; + line = 0; + pw = 0; + break; + } + line[strcspn(line, "\n")] = 0; + + s = line; + pw->pw_name = s++; + if (!(s = strchr(s, ':'))) continue; + + *s++ = 0; pw->pw_passwd = s; + if (!(s = strchr(s, ':'))) continue; + + *s++ = 0; pw->pw_uid = atou(&s); + if (*s != ':') continue; + + *s++ = 0; pw->pw_gid = atou(&s); + if (*s != ':') continue; + + *s++ = 0; pw->pw_gecos = s; + if (!(s = strchr(s, ':'))) continue; + + *s++ = 0; pw->pw_dir = s; + if (!(s = strchr(s, ':'))) continue; + + *s++ = 0; pw->pw_shell = s; + break; + } + *res = pw; + if (rv) errno = rv; + return rv; +} + +#endif // ifdef BSD diff --git a/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.c b/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.c new file mode 100644 index 0000000..28f0e0d --- /dev/null +++ b/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.c @@ -0,0 +1,458 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An NSS module which adds supports for file /etc/oslogin_passwd.cache + +#include "nss_cache_oslogin.h" +#include "../compat.h" + +#include + +// Locking implementation: use pthreads. +#include +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#define NSS_CACHE_OSLOGIN_LOCK() \ + do { \ + pthread_mutex_lock(&mutex); \ + } while (0) +#define NSS_CACHE_OSLOGIN_UNLOCK() \ + do { \ + pthread_mutex_unlock(&mutex); \ + } while (0) + +static FILE *p_file = NULL; +static char p_filename[NSS_CACHE_OSLOGIN_PATH_LENGTH] = NSS_CACHE_OSLOGIN_PATH; +#ifdef BSD +extern int fgetpwent_r(FILE *, struct passwd *, char *, size_t, + struct passwd **); +#endif // ifdef BSD + +/* Common return code routine for all *ent_r_locked functions. + * We need to return TRYAGAIN if the underlying files guy raises ERANGE, + * so that our caller knows to try again with a bigger buffer. + */ + +static inline enum nss_status _nss_cache_oslogin_ent_bad_return_code( + int errnoval) { + enum nss_status ret; + + switch (errnoval) { + case ERANGE: + DEBUG("ERANGE: Try again with a bigger buffer\n"); + ret = NSS_STATUS_TRYAGAIN; + break; + case ENOENT: + default: + DEBUG("ENOENT or default case: Not found\n"); + ret = NSS_STATUS_NOTFOUND; + }; + return ret; +} + +// +// Binary search routines below here +// + +int _nss_cache_oslogin_bsearch2_compare(const void *key, const void *value) { + struct nss_cache_oslogin_args *args = (struct nss_cache_oslogin_args *)key; + const char *value_text = (const char *)value; + + // Using strcmp as the generation of the index sorts without + // locale awareness. + return strcmp(args->lookup_key, value_text); +} + +enum nss_status _nss_cache_oslogin_bsearch2(struct nss_cache_oslogin_args *args, + int *errnop) { + enum nss_cache_oslogin_match (*lookup)( + FILE *, struct nss_cache_oslogin_args *) = args->lookup_function; + FILE *file = NULL; + FILE *system_file_stream = NULL; + struct stat system_file; + struct stat sorted_file; + enum nss_status ret = 100; + long offset = 0; + void *mapped_data = NULL; + + file = fopen(args->sorted_filename, "r"); + if (file == NULL) { + DEBUG("error opening %s\n", args->sorted_filename); + return NSS_STATUS_UNAVAIL; + } + + // if the sorted file is older than the system file, do not risk stale + // data and abort + // TODO(vasilios): should be a compile or runtime option + if (stat(args->system_filename, &system_file) != 0) { + DEBUG("failed to stat %s\n", args->system_filename); + fclose(file); + return NSS_STATUS_UNAVAIL; + } + if (fstat(fileno(file), &sorted_file) != 0) { + DEBUG("failed to stat %s\n", args->sorted_filename); + fclose(file); + return NSS_STATUS_UNAVAIL; + } + if (difftime(system_file.st_mtime, sorted_file.st_mtime) > 0) { + DEBUG("%s may be stale, aborting lookup\n", args->sorted_filename); + fclose(file); + return NSS_STATUS_UNAVAIL; + } + + mapped_data = + mmap(NULL, sorted_file.st_size, PROT_READ, MAP_PRIVATE, fileno(file), 0); + if (mapped_data == MAP_FAILED) { + DEBUG("mmap failed\n"); + fclose(file); + return NSS_STATUS_UNAVAIL; + } + + const char *data = (const char *)mapped_data; + while (*data != '\n') { + ++data; + } + long entry_size = data - (const char *)mapped_data + 1; + long entry_count = sorted_file.st_size / entry_size; + + void *entry = bsearch(args, mapped_data, entry_count, entry_size, + &_nss_cache_oslogin_bsearch2_compare); + if (entry != NULL) { + const char *entry_text = entry; + sscanf(entry_text + strlen(entry_text) + 1, "%ld", &offset); + } + + if (munmap(mapped_data, sorted_file.st_size) == -1) { + DEBUG("munmap failed\n"); + } + fclose(file); + + if (entry == NULL) { + return NSS_STATUS_NOTFOUND; + } + + system_file_stream = fopen(args->system_filename, "r"); + if (system_file_stream == NULL) { + DEBUG("error opening %s\n", args->system_filename); + return NSS_STATUS_UNAVAIL; + } + + if (fseek(system_file_stream, offset, SEEK_SET) != 0) { + DEBUG("fseek fail\n"); + return NSS_STATUS_UNAVAIL; + } + + switch (lookup(system_file_stream, args)) { + case NSS_CACHE_OSLOGIN_EXACT: + ret = NSS_STATUS_SUCCESS; + break; + case NSS_CACHE_OSLOGIN_ERROR: + if (errno == ERANGE) { + // let the caller retry + *errnop = errno; + ret = _nss_cache_oslogin_ent_bad_return_code(*errnop); + } + break; + default: + ret = NSS_STATUS_UNAVAIL; + break; + } + + fclose(system_file_stream); + return ret; +} + +// +// Routines for passwd map defined below here +// + +// _nss_cache_oslogin_setpwent_path() +// Helper function for testing + +extern char *_nss_cache_oslogin_setpwent_path(const char *path) { + DEBUG("%s %s\n", "Setting p_filename to", path); + return strncpy(p_filename, path, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); +} + +// _nss_cache_oslogin_pwuid_wrap() +// Internal wrapper for binary searches, using uid-specific calls. + +static enum nss_cache_oslogin_match _nss_cache_oslogin_pwuid_wrap( + FILE *file, struct nss_cache_oslogin_args *args) { + struct passwd *result = args->lookup_result; + uid_t *uid = args->lookup_value; + + if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) { + if (result->pw_uid == *uid) { + DEBUG("SUCCESS: found user %d:%s\n", result->pw_uid, result->pw_name); + return NSS_CACHE_OSLOGIN_EXACT; + } + DEBUG("Failed match at uid %d\n", result->pw_uid); + if (result->pw_uid > *uid) { + return NSS_CACHE_OSLOGIN_HIGH; + } else { + return NSS_CACHE_OSLOGIN_LOW; + } + } + + return NSS_CACHE_OSLOGIN_ERROR; +} + +// _nss_cache_oslogin_pwnam_wrap() +// Internal wrapper for binary searches, using username-specific calls. + +static enum nss_cache_oslogin_match _nss_cache_oslogin_pwnam_wrap( + FILE *file, struct nss_cache_oslogin_args *args) { + struct passwd *result = args->lookup_result; + char *name = args->lookup_value; + int ret; + + if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) { + ret = strcoll(result->pw_name, name); + if (ret == 0) { + DEBUG("SUCCESS: found user %s\n", result->pw_name); + return NSS_CACHE_OSLOGIN_EXACT; + } + DEBUG("Failed match at name %s\n", result->pw_name); + if (ret > 0) { + return NSS_CACHE_OSLOGIN_HIGH; + } else { + return NSS_CACHE_OSLOGIN_LOW; + } + } + + return NSS_CACHE_OSLOGIN_ERROR; +} + +// _nss_cache_oslogin_setpwent_locked() +// Internal setup routine + +static enum nss_status _nss_cache_oslogin_setpwent_locked(void) { + DEBUG("%s %s\n", "Opening", p_filename); + p_file = fopen(p_filename, "r"); + + if (p_file) { + return NSS_STATUS_SUCCESS; + } else { + return NSS_STATUS_UNAVAIL; + } +} + +// _nss_cache_oslogin_setpwent() +// Called by NSS to open the passwd file +// 'stayopen' parameter is ignored. + +enum nss_status _nss_cache_oslogin_setpwent(int stayopen) { + enum nss_status ret; + NSS_CACHE_OSLOGIN_LOCK(); + ret = _nss_cache_oslogin_setpwent_locked(); + NSS_CACHE_OSLOGIN_UNLOCK(); + return ret; +} + +// _nss_cache_oslogin_endpwent_locked() +// Internal close routine + +static enum nss_status _nss_cache_oslogin_endpwent_locked(void) { + DEBUG("Closing passwd.cache\n"); + if (p_file) { + fclose(p_file); + p_file = NULL; + } + return NSS_STATUS_SUCCESS; +} + +// _nss_cache_oslogin_endpwent() +// Called by NSS to close the passwd file + +enum nss_status _nss_cache_oslogin_endpwent(void) { + enum nss_status ret; + NSS_CACHE_OSLOGIN_LOCK(); + ret = _nss_cache_oslogin_endpwent_locked(); + NSS_CACHE_OSLOGIN_UNLOCK(); + return ret; +} + +// _nss_cache_oslogin_getpwent_r_locked() +// Called internally to return the next entry from the passwd file + +static enum nss_status _nss_cache_oslogin_getpwent_r_locked( + struct passwd *result, char *buffer, size_t buflen, int *errnop) { + enum nss_status ret = NSS_STATUS_SUCCESS; + + if (p_file == NULL) { + DEBUG("p_file == NULL, going to setpwent\n"); + ret = _nss_cache_oslogin_setpwent_locked(); + } + + if (ret == NSS_STATUS_SUCCESS) { + if (fgetpwent_r(p_file, result, buffer, buflen, &result) == 0) { + DEBUG("Returning user %d:%s\n", result->pw_uid, result->pw_name); + } else { + if (errno == ENOENT) { + errno = 0; + } + *errnop = errno; + ret = _nss_cache_oslogin_ent_bad_return_code(*errnop); + } + } + + return ret; +} + +// _nss_cache_oslogin_getpwent_r() +// Called by NSS to look up next entry in passwd file + +enum nss_status _nss_cache_oslogin_getpwent_r(struct passwd *result, + char *buffer, size_t buflen, + int *errnop) { + enum nss_status ret; + NSS_CACHE_OSLOGIN_LOCK(); + ret = _nss_cache_oslogin_getpwent_r_locked(result, buffer, buflen, errnop); + NSS_CACHE_OSLOGIN_UNLOCK(); + return ret; +} + +// _nss_cache_oslogin_getpwuid_r() +// Find a user account by uid + +enum nss_status _nss_cache_oslogin_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, + int *errnop) { + char filename[NSS_CACHE_OSLOGIN_PATH_LENGTH]; + struct nss_cache_oslogin_args args; + enum nss_status ret; + + strncpy(filename, p_filename, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); + if (strlen(filename) > NSS_CACHE_OSLOGIN_PATH_LENGTH - 7) { + DEBUG("filename too long\n"); + return NSS_STATUS_UNAVAIL; + } + strncat(filename, ".ixuid", 6); + + args.sorted_filename = filename; + args.system_filename = p_filename; + args.lookup_function = _nss_cache_oslogin_pwuid_wrap; + args.lookup_value = &uid; + args.lookup_result = result; + args.buffer = buffer; + args.buflen = buflen; + char uid_text[11]; + snprintf(uid_text, sizeof(uid_text), "%d", uid); + args.lookup_key = uid_text; + args.lookup_key_length = strlen(uid_text); + + DEBUG("Binary search for uid %d\n", uid); + NSS_CACHE_OSLOGIN_LOCK(); + ret = _nss_cache_oslogin_bsearch2(&args, errnop); + + if (ret == NSS_STATUS_UNAVAIL) { + DEBUG("Binary search failed, falling back to full linear search\n"); + ret = _nss_cache_oslogin_setpwent_locked(); + + if (ret == NSS_STATUS_SUCCESS) { + while ((ret = _nss_cache_oslogin_getpwent_r_locked( + result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) { + if (result->pw_uid == uid) break; + } + } + } + + _nss_cache_oslogin_endpwent_locked(); + NSS_CACHE_OSLOGIN_UNLOCK(); + + return ret; +} + +// _nss_cache_oslogin_getpwnam_r() +// Find a user account by name + +enum nss_status _nss_cache_oslogin_getpwnam_r(const char *name, + struct passwd *result, + char *buffer, size_t buflen, + int *errnop) { + char *pw_name; + char filename[NSS_CACHE_OSLOGIN_PATH_LENGTH]; + struct nss_cache_oslogin_args args; + enum nss_status ret; + + NSS_CACHE_OSLOGIN_LOCK(); + + // name is a const char, we need a non-const copy + pw_name = malloc(strlen(name) + 1); + if (pw_name == NULL) { + DEBUG("malloc error\n"); + return NSS_STATUS_UNAVAIL; + } + strncpy(pw_name, name, strlen(name) + 1); + + strncpy(filename, p_filename, NSS_CACHE_OSLOGIN_PATH_LENGTH - 1); + if (strlen(filename) > NSS_CACHE_OSLOGIN_PATH_LENGTH - 8) { + DEBUG("filename too long\n"); + free(pw_name); + return NSS_STATUS_UNAVAIL; + } + strncat(filename, ".ixname", 7); + + args.sorted_filename = filename; + args.system_filename = p_filename; + args.lookup_function = _nss_cache_oslogin_pwnam_wrap; + args.lookup_value = pw_name; + args.lookup_result = result; + args.buffer = buffer; + args.buflen = buflen; + args.lookup_key = pw_name; + args.lookup_key_length = strlen(pw_name); + + DEBUG("Binary search for user %s\n", pw_name); + ret = _nss_cache_oslogin_bsearch2(&args, errnop); + + if (ret == NSS_STATUS_UNAVAIL) { + DEBUG("Binary search failed, falling back to full linear search\n"); + ret = _nss_cache_oslogin_setpwent_locked(); + + if (ret == NSS_STATUS_SUCCESS) { + while ((ret = _nss_cache_oslogin_getpwent_r_locked( + result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) { + if (!strcmp(result->pw_name, name)) break; + } + } + } + + free(pw_name); + _nss_cache_oslogin_endpwent_locked(); + NSS_CACHE_OSLOGIN_UNLOCK(); + + return ret; +} + +NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r); +NSS_METHOD_PROTOTYPE(__nss_compat_setpwent); +NSS_METHOD_PROTOTYPE(__nss_compat_endpwent); + +DECLARE_NSS_METHOD_TABLE(methods, + { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, + (void*)_nss_cache_oslogin_getpwnam_r }, + { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, + (void*)_nss_cache_oslogin_getpwuid_r }, + { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, + (void*)_nss_cache_oslogin_getpwent_r }, + { NSDB_PASSWD, "endpwent", __nss_compat_endpwent, + (void*)_nss_cache_oslogin_endpwent }, + { NSDB_PASSWD, "setpwent", __nss_compat_setpwent, + (void*)_nss_cache_oslogin_setpwent }, +) + +NSS_REGISTER_METHODS(methods) diff --git a/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.h b/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.h new file mode 100644 index 0000000..25c7274 --- /dev/null +++ b/packages/google-compute-engine-oslogin/nss_module/nss_cache_oslogin.h @@ -0,0 +1,65 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NSS_CACHE_OSLOGIN_H +#define NSS_CACHE_OSLOGIN_H + +#ifdef DEBUG +#undef DEBUG +#define DEBUG(fmt, args...) \ + do { \ + fprintf(stderr, fmt, ##args); \ + } while (0) +#else +#define DEBUG(fmt, ...) \ + do { \ + } while (0) +#endif /* DEBUG */ + +#define NSS_CACHE_OSLOGIN_PATH_LENGTH 255 +extern char *_nss_cache_oslogin_setpwent_path(const char *path); + +enum nss_cache_oslogin_match { + NSS_CACHE_OSLOGIN_EXACT = 0, + NSS_CACHE_OSLOGIN_HIGH = 1, + NSS_CACHE_OSLOGIN_LOW = 2, + NSS_CACHE_OSLOGIN_ERROR = 3, +}; + +struct nss_cache_oslogin_args { + char *system_filename; + char *sorted_filename; + void *lookup_function; + void *lookup_value; + void *lookup_result; + char *buffer; + size_t buflen; + char *lookup_key; + size_t lookup_key_length; +}; + +#endif /* NSS_CACHE_OSLOGIN_H */ diff --git a/packages/google-compute-engine-oslogin/packaging/debian/links b/packages/google-compute-engine-oslogin/packaging/debian/links deleted file mode 100644 index 7d96d15..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/links +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/man/man8/nss-oslogin.8.gz usr/share/man/man8/libnss_oslogin.so.2.8.gz -usr/share/man/man8/nss-cache-oslogin.8.gz usr/share/man/man8/libnss_cache_oslogin.so.2.8.gz diff --git a/packages/google-compute-engine-oslogin/packaging/debian/manpages b/packages/google-compute-engine-oslogin/packaging/debian/manpages deleted file mode 100644 index 2156c20..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/manpages +++ /dev/null @@ -1,2 +0,0 @@ -nss_module/nss-oslogin.8 -nss_module/nss-cache-oslogin.8 diff --git a/packages/google-compute-engine-oslogin/packaging/debian/rules b/packages/google-compute-engine-oslogin/packaging/debian/rules index aa0f238..8ae94b8 100755 --- a/packages/google-compute-engine-oslogin/packaging/debian/rules +++ b/packages/google-compute-engine-oslogin/packaging/debian/rules @@ -3,6 +3,4 @@ dh $@ override_dh_auto_install: - dh_auto_install -- PAM_INSTALL_PATH=/lib/$(DEB_HOST_MULTIARCH)/security \ - BIN_INSTALL_PATH=/usr/bin NSS_INSTALL_PATH=/lib/$(DEB_HOST_MULTIARCH)/ \ - MAKE_LINKS=true + dh_auto_install -- LIBDIR=/lib/$(DEB_HOST_MULTIARCH) diff --git a/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec b/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec index b8b0e67..f93dfff 100644 --- a/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec +++ b/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec @@ -41,8 +41,6 @@ Requires: policycoreutils-python Requires: boost-regex Requires: json-c -%define pam_install_path /%{_lib}/security - %description This package contains several libraries and changes to enable OS Login functionality for Google Compute Engine. @@ -53,26 +51,28 @@ for Google Compute Engine. %setup %build -make %{?_smp_mflags} LIBS="-lcurl -ljson-c -lboost_regex" +make %{?_smp_mflags} LDLIBS="-lcurl -ljson-c -lboost_regex" %install rm -rf %{buildroot} -make install DESTDIR=%{buildroot} NSS_INSTALL_PATH=/%{_lib} PAM_INSTALL_PATH=%{pam_install_path} INSTALL_SELINUX=true +make install DESTDIR=%{buildroot} LIBDIR=/%{_lib} INSTALL_SELINUX=y %files %doc -%attr(0755,-,-) /%{_lib}/libnss_%{name}-%{version}.so -%attr(0755,-,-) /%{_lib}/libnss_cache_%{name}-%{version}.so -%if 0%{?rhel} == 8 +/%{_lib}/libnss_oslogin-%{version}.so +/%{_lib}/libnss_cache_oslogin-%{version}.so /%{_lib}/libnss_oslogin.so.2 /%{_lib}/libnss_cache_oslogin.so.2 -%endif -%attr(0755,-,-) %{pam_install_path}/pam_oslogin_admin.so -%attr(0755,-,-) %{pam_install_path}/pam_oslogin_login.so +/%{_lib}/security/pam_oslogin_admin.so +/%{_lib}/security/pam_oslogin_login.so /usr/bin/google_authorized_keys /usr/bin/google_oslogin_control /usr/bin/google_oslogin_nss_cache /usr/share/selinux/packages/oslogin.pp +%{_mandir}/man8/nss-oslogin.8.gz +%{_mandir}/man8/libnss_oslogin.so.2.8.gz +%{_mandir}/man8/nss-cache-oslogin.8.gz +%{_mandir}/man8/libnss_cache_oslogin.so.2.8.gz %post /sbin/ldconfig diff --git a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh b/packages/google-compute-engine-oslogin/packaging/setup_deb.sh index 7788a40..8dfea94 100755 --- a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh +++ b/packages/google-compute-engine-oslogin/packaging/setup_deb.sh @@ -39,6 +39,6 @@ cd ${NAME}-${VERSION} cp -r ${working_dir}/packaging/debian ./ -debuild -us -uc +DEB_BUILD_OPTIONS=noddebs debuild -us -uc popd -- cgit v1.2.1