summaryrefslogtreecommitdiff
path: root/packages/google-compute-engine-oslogin/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/google-compute-engine-oslogin/src')
-rw-r--r--packages/google-compute-engine-oslogin/src/Makefile86
-rw-r--r--packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc78
-rw-r--r--packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc119
-rw-r--r--packages/google-compute-engine-oslogin/src/include/compat.h62
-rw-r--r--packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h65
-rw-r--r--packages/google-compute-engine-oslogin/src/include/oslogin_utils.h238
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c87
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c274
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc209
-rw-r--r--packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc100
-rw-r--r--packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc273
-rw-r--r--packages/google-compute-engine-oslogin/src/utils.cc864
12 files changed, 0 insertions, 2455 deletions
diff --git a/packages/google-compute-engine-oslogin/src/Makefile b/packages/google-compute-engine-oslogin/src/Makefile
deleted file mode 100644
index 8b5d339..0000000
--- a/packages/google-compute-engine-oslogin/src/Makefile
+++ /dev/null
@@ -1,86 +0,0 @@
-SHELL = /bin/sh
-TOPDIR = $(realpath ..)
-
-VERSION = 20190801.00
-
-CPPFLAGS = -Iinclude -I/usr/include/json-c
-FLAGS = -fPIC -Wall -g
-CFLAGS = $(FLAGS) -Wstrict-prototypes
-CXXFLAGS = $(FLAGS)
-
-LDFLAGS = -shared -Wl,-soname,$(SONAME)
-LDLIBS = -lcurl -ljson-c
-PAMLIBS = -lpam $(LDLIBS)
-
-# Paths which should be overrideable.
-
-PREFIX = /usr
-LIBDIR = $(PREFIX)/lib
-BINDIR = $(PREFIX)/bin
-PAMDIR = $(LIBDIR)/security
-MANDIR = /usr/share/man
-
-NSS_OSLOGIN_SONAME = libnss_oslogin.so.2
-NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2
-
-NSS_OSLOGIN = libnss_oslogin-$(VERSION).so
-NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so
-
-PAM_LOGIN = pam_oslogin_login.so
-PAM_ADMIN = pam_oslogin_admin.so
-
-BINARIES = google_oslogin_nss_cache google_authorized_keys
-
-all : $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(PAM_ADMIN) $(BINARIES)
-
-clean :
- rm -f $(BINARIES)
- find . -type f \( -iname '*.o' -o -iname '*.so' \) -delete
-
-.PHONY : all clean install
-
-# NSS modules.
-
-$(NSS_OSLOGIN) : SONAME = $(NSS_OSLOGIN_SONAME)
-$(NSS_OSLOGIN) : nss/nss_oslogin.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)
-
-$(NSS_CACHE_OSLOGIN) : SONAME = $(NSS_CACHE_OSLOGIN_SONAME)
-$(NSS_CACHE_OSLOGIN) : nss/nss_cache_oslogin.o nss/compat/getpwent_r.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)
-
-# PAM modules
-
-$(PAM_LOGIN) : pam/pam_oslogin_login.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
-
-$(PAM_ADMIN) : pam/pam_oslogin_admin.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
-
-# Utilities.
-
-google_authorized_keys : authorized_keys/authorized_keys.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
-
-google_oslogin_nss_cache: cache_refresh/cache_refresh.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
-
-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)
- ln -sf $(NSS_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_OSLOGIN_SONAME)
- ln -sf $(NSS_CACHE_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME)
- install -m 0644 -t $(DESTDIR)$(PAMDIR) $(PAM_ADMIN) $(PAM_LOGIN)
- install -m 0755 -t $(DESTDIR)$(BINDIR) $(BINARIES) $(TOPDIR)/google_oslogin_control
- install -m 0644 -t $(DESTDIR)$(MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/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
-ifdef INSTALL_SELINUX
- install -d $(DESTDIR)/usr/share/selinux/packages
- install -m 0644 -t $(DESTDIR)/usr/share/selinux/packages $(TOPDIR)/selinux/oslogin.pp
-endif
diff --git a/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc b/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc
deleted file mode 100644
index 3eda59c..0000000
--- a/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 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 <iostream>
-#include <sstream>
-#include <string>
-
-#include <oslogin_utils.h>
-
-using std::cout;
-using std::endl;
-using std::string;
-
-using oslogin_utils::HttpGet;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSshKeys;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::kMetadataServerUrl;
-
-int main(int argc, char* argv[]) {
- if (argc != 2) {
- cout << "usage: authorized_keys [username]" << endl;
- return 1;
- }
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(argv[1]);
- string user_response;
- long http_code = 0;
- if (!HttpGet(url.str(), &user_response, &http_code) ||
- user_response.empty() || http_code != 200) {
- if (http_code == 404) {
- // Return 0 if the user is not an oslogin user. If we returned a failure
- // code, we would populate auth.log with useless error messages.
- return 0;
- }
- return 1;
- }
- string email;
- if (!ParseJsonToEmail(user_response, &email) || email.empty()) {
- return 1;
- }
- // Redundantly verify that this user has permission to log in to this VM.
- // Normally the PAM module determines this, but in the off chance a transient
- // error causes the PAM module to permit a user without login permissions,
- // perform the same check here. If this fails, we can guarantee that we won't
- // accidentally allow a user to log in without permissions.
- url.str("");
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=login";
- string auth_response;
- if (!HttpGet(url.str(), &auth_response, &http_code) || http_code != 200 ||
- auth_response.empty()) {
- return 1;
- }
- if (!ParseJsonToSuccess(auth_response)) {
- return 1;
- }
- // At this point, we've verified the user can log in. Grab the ssh keys from
- // the user response.
- std::vector<string> ssh_keys = ParseJsonToSshKeys(user_response);
- for (int i = 0; i < ssh_keys.size(); i++) {
- cout << ssh_keys[i] << endl;
- }
- return 0;
-}
diff --git a/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc b/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc
deleted file mode 100644
index bc4a10c..0000000
--- a/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc
+++ /dev/null
@@ -1,119 +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 <errno.h>
-#include <nss.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <fstream>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-
-using oslogin_utils::BufferManager;
-using oslogin_utils::MutexLock;
-using oslogin_utils::NssCache;
-
-// File paths for the nss cache file.
-static const char kDefaultFilePath[] = K_DEFAULT_FILE_PATH;
-static const char kDefaultBackupFilePath[] = K_DEFAULT_BACKUP_FILE_PATH;
-
-// Local NSS Cache size. This affects the maximum number of passwd entries per
-// http request.
-static const uint64_t kNssCacheSize = 2048;
-
-// Passwd buffer size. We are guaranteed that a single OS Login user will not
-// exceed 32k.
-static const uint64_t kPasswdBufferSize = 32768;
-
-static NssCache nss_cache(kNssCacheSize);
-
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-int main(int argc, char* argv[]) {
- int error_code = 0;
- // Temporary buffer to hold passwd entries before writing.
- char buffer[kPasswdBufferSize];
- struct passwd pwd;
-
- // Perform the writes under a global lock.
- MutexLock ml(&cache_mutex);
- nss_cache.Reset();
-
- // Check if there is a cache already.
- struct stat stat_buf;
- bool backup = !stat(kDefaultFilePath, &stat_buf);
- if (backup) {
- // Write a backup file first, in case lookup fails.
- error_code = rename(kDefaultFilePath, kDefaultBackupFilePath);
- if (error_code) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Could not create backup file.");
- closelog();
- return error_code;
- }
- }
-
- std::ofstream cache_file(kDefaultFilePath);
- if (cache_file.fail()) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Failed to open file %s.", kDefaultFilePath);
- closelog();
- return -1;
- }
- chown(kDefaultFilePath, 0, 0);
- chmod(kDefaultFilePath, S_IRUSR | S_IWUSR | S_IROTH);
-
- while (!nss_cache.OnLastPage() || nss_cache.HasNextPasswd()) {
- BufferManager buffer_manager(buffer, kPasswdBufferSize);
- if (!nss_cache.NssGetpwentHelper(&buffer_manager, &pwd, &error_code)) {
- break;
- }
- cache_file << pwd.pw_name << ":" << pwd.pw_passwd << ":" << pwd.pw_uid
- << ":" << pwd.pw_gid << ":" << pwd.pw_gecos << ":" << pwd.pw_dir
- << ":" << pwd.pw_shell << "\n";
- }
- cache_file.close();
-
- // Check for errors.
- if (error_code) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- if (error_code == ERANGE) {
- syslog(LOG_ERR, "Received unusually large passwd entry.");
- } else if (error_code == EINVAL) {
- syslog(LOG_ERR, "Encountered malformed passwd entry.");
- } else {
- syslog(LOG_ERR, "Unknown error while retrieving passwd entry.");
- }
- // Restore the backup.
- if (backup) {
- if (rename(kDefaultBackupFilePath, kDefaultFilePath)) {
- syslog(LOG_ERR, "Could not restore data from backup file.");
- }
- }
- closelog();
- }
-
- // Remove the backup file on success.
- if (!error_code && backup) {
- remove(kDefaultBackupFilePath);
- }
- return error_code;
-}
diff --git a/packages/google-compute-engine-oslogin/src/include/compat.h b/packages/google-compute-engine-oslogin/src/include/compat.h
deleted file mode 100644
index 84a1a6f..0000000
--- a/packages/google-compute-engine-oslogin/src/include/compat.h
+++ /dev/null
@@ -1,62 +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.
-
-#ifndef OSLOGIN_COMPAT_H
-#define OSLOGIN_COMPAT_H
-
-#ifdef __FreeBSD__
-
-#include <nsswitch.h>
-
-#define DECLARE_NSS_METHOD_TABLE(name, ...) \
- static ns_mtab name[] = {__VA_ARGS__};
-
-#define NSS_METHOD(method, func) { \
- .database = NSDB_PASSWD, \
- .name = #method, \
- .method = __nss_compat_ ## method, \
- .mdata = (void*)func \
-}
-
-#define NSS_REGISTER_METHODS(methods) ns_mtab * \
-nss_module_register (const char *name, unsigned int *size, \
- nss_module_unregister_fn *unregister) \
-{ \
- *size = sizeof (methods) / sizeof (methods[0]); \
- *unregister = NULL; \
- return (methods); \
-}
-
-#define NSS_CACHE_OSLOGIN_PATH "/usr/local/etc/oslogin_passwd.cache"
-#define K_DEFAULT_FILE_PATH "/usr/local/etc/oslogin_passwd.cache"
-#define K_DEFAULT_BACKUP_FILE_PATH "/usr/local/etc/oslogin_passwd.cache.bak"
-#define PAM_SYSLOG(pamh, ...) syslog(__VA_ARGS__)
-#define DEFAULT_SHELL "/bin/sh"
-
-#else /* __FreeBSD__ */
-
-#include <security/pam_ext.h>
-
-#define DECLARE_NSS_METHOD_TABLE(name, ...)
-#define NSS_CACHE_OSLOGIN_PATH "/etc/oslogin_passwd.cache"
-#define NSS_METHOD_PROTOTYPE(m)
-#define NSS_REGISTER_METHODS(methods)
-#define K_DEFAULT_FILE_PATH "/etc/oslogin_passwd.cache"
-#define K_DEFAULT_BACKUP_FILE_PATH "/etc/oslogin_passwd.cache.bak"
-#define PAM_SYSLOG pam_syslog
-#define DEFAULT_SHELL "/bin/bash"
-
-#endif /* __FreeBSD__ */
-
-#endif /* OSLOGIN_COMPAT_H */
diff --git a/packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h b/packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h
deleted file mode 100644
index 25c7274..0000000
--- a/packages/google-compute-engine-oslogin/src/include/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 <errno.h>
-#include <nss.h>
-#include <stdlib.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <time.h>
-#include <unistd.h>
-
-#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/src/include/oslogin_utils.h b/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
deleted file mode 100644
index 82763bf..0000000
--- a/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2017 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 <grp.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#define TOTP "TOTP"
-#define AUTHZEN "AUTHZEN"
-#define INTERNAL_TWO_FACTOR "INTERNAL_TWO_FACTOR"
-#define IDV_PREREGISTERED_PHONE "IDV_PREREGISTERED_PHONE"
-
-using std::string;
-using std::vector;
-
-namespace oslogin_utils {
-
-// Metadata server URL.
-static const char kMetadataServerUrl[] =
- "http://metadata.google.internal/computeMetadata/v1/oslogin/";
-
-// BufferManager encapsulates and manages a buffer and length. This class is not
-// thread safe.
-class BufferManager {
- public:
- // Create a BufferManager that will dole out chunks of buf as requested.
- BufferManager(char* buf, size_t buflen);
-
- // Copies a string to the buffer and sets the buffer to point to that
- // string. Copied string is guaranteed to be null-terminated.
- // Returns false and sets errnop if there is not enough space left in the
- // buffer for the string.
- bool AppendString(const string& value, char** buffer, int* errnop);
-
- // Return a pointer to a buffer of size bytes. Returns NULL and sets errnop to
- // ERANGE if there is not enough space left in the buffer for the request.
- void* Reserve(size_t bytes, int* errnop);
-
- private:
- // Whether there is space available in the buffer.
- bool CheckSpaceAvailable(size_t bytes_to_write) const;
-
- char* buf_;
- size_t buflen_;
-
- // Not copyable or assignable.
- BufferManager& operator=(const BufferManager&);
- BufferManager(const BufferManager&);
-};
-
-// Challenge represents a security challenge available to the user.
-class Challenge {
- public:
- int id;
- string type;
- string status;
-};
-
-class Group {
- public:
- int64_t gid;
- string name;
-};
-
-// NssCache caches passwd entries for getpwent_r. This is used to prevent making
-// an HTTP call on every getpwent_r invocation. Stores up to cache_size entries
-// at a time. This class is not thread safe.
-class NssCache {
- public:
- explicit NssCache(int cache_size);
-
- // Clears and resets the NssCache.
- void Reset();
-
- // Whether the cache has a next passwd entry.
- bool HasNextPasswd();
-
- // Whether the cache has reached the last page of the database.
- bool OnLastPage() { return on_last_page_; }
-
- // Grabs the next passwd entry. Returns true on success. Sets errnop on
- // failure.
- bool GetNextPasswd(BufferManager* buf, passwd* result, int* errnop);
-
- // Loads a json array of passwd entries in the cache, starting at the
- // beginning of the cache. This will remove all previous entries in the cache.
- // response is expected to be a JSON array of passwd entries. Returns
- // true on success.
- bool LoadJsonArrayToCache(string response);
-
- // Helper method that effectively implements the getpwent_r nss method. Each
- // call will iterate through the OsLogin database and return the next entry.
- // Internally, the cache will keep track of pages of passwd entries, and will
- // make an http call to the server if necessary to retrieve additional
- // entries. Returns whether passwd retrieval was successful. If true, the
- // passwd result will contain valid data.
- bool NssGetpwentHelper(BufferManager* buf, struct passwd* result,
- int* errnop);
-
- // Returns the page token for requesting the next page of passwd entries.
- string GetPageToken() { return page_token_; }
-
- private:
- // The maximum size of the cache.
- int cache_size_;
-
- // Vector of passwds. These are represented as stringified json object.
- std::vector<std::string> passwd_cache_;
-
- // The page token for requesting the next page of passwds.
- std::string page_token_;
-
- // Index for requesting the next passwd from the cache.
- uint32_t index_;
-
- // Whether the NssCache has reached the last page of the database.
- bool on_last_page_;
-
- // Not copyable or assignable.
- NssCache& operator=(const NssCache&);
- NssCache(const NssCache&);
-};
-
-// Auto locks and unlocks a given mutex on construction/destruction. Does NOT
-// take ownership of the mutex.
-class MutexLock {
- public:
- explicit MutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
- pthread_mutex_lock(mutex_);
- }
-
- ~MutexLock() { pthread_mutex_unlock(mutex_); }
-
- private:
- // The mutex to lock/unlock
- pthread_mutex_t* const mutex_;
-
- // Not copyable or assignable.
- MutexLock& operator=(const MutexLock);
- MutexLock(const MutexLock&);
-};
-
-// Callback invoked when Curl completes a request.
-size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);
-
-// Uses Curl to issue a GET request to the given url. Returns whether the
-// request was successful. If successful, the result from the server will be
-// stored in response, and the HTTP response code will be stored in http_code.
-bool HttpGet(const string& url, string* response, long* http_code);
-bool HttpPost(const string& url, const string& data, string* response,
- long* http_code);
-
-// Returns whether user_name is a valid OsLogin user name.
-bool ValidateUserName(const string& user_name);
-
-// URL encodes the given parameter. Returns the encoded parameter.
-std::string UrlEncode(const string& param);
-
-// Returns true if the given passwd contains valid fields. If pw_dir, pw_shell,
-// or pw_passwd are not set, this will populate these entries with default
-// values.
-bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop);
-
-// Adds users and associated array of char* to provided buffer and store pointer
-// to array in result.gr_mem.
-bool AddUsersToGroup(std::vector<string> users, struct group* result,
- BufferManager* buf, int* errnop);
-
-// Iterates through all groups until one matching provided group is found,
-// replacing gr_name with a buffermanager provided string.
-bool FindGroup(struct group* grp, BufferManager* buf, int* errnop);
-
-// Iterates through all users for a group, storing results in a provided string
-// vector.
-bool GetUsersForGroup(string groupname, std::vector<string>* users,
- int* errnop);
-
-// Iterates through all groups for a user, storing results in a provided string
-// vector.
-bool GetGroupsForUser(string username, std::vector<Group>* groups, int* errnop);
-
-// Parses a JSON groups response, storing results in a provided Group vector.
-bool ParseJsonToGroups(const string& json, std::vector<Group>* groups);
-
-// Parses a JSON users response, storing results in a provided string vector.
-bool ParseJsonToUsers(const string& json, std::vector<string>* users);
-
-// Parses a JSON LoginProfiles response for SSH keys. Returns a vector of valid
-// ssh_keys. A key is considered valid if it's expiration date is greater than
-// current unix time.
-std::vector<string> ParseJsonToSshKeys(const string& json);
-
-// Parses a JSON object and returns the value associated with a given key.
-bool ParseJsonToKey(const string& json, const string& key, string* response);
-
-// Parses a JSON LoginProfiles response and returns the email under the "name"
-// field.
-bool ParseJsonToEmail(const string& json, string* email);
-
-// Parses a JSON LoginProfiles response and populates the passwd struct with the
-// corresponding values set in the JSON object. Returns whether the parse was
-// successful or not. If unsuccessful, errnop will also be set.
-bool ParseJsonToPasswd(const string& response, struct passwd* result,
- BufferManager* buf, int* errnop);
-
-// Parses a JSON adminLogin or login response and returns whether the user has
-// the requested privilege.
-bool ParseJsonToSuccess(const string& json);
-
-// Parses a JSON startSession response into a vector of Challenge objects.
-bool ParseJsonToChallenges(const string& json, vector<Challenge>* challenges);
-
-// Calls the startSession API.
-bool StartSession(const string& email, string* response);
-
-// Calls the continueSession API.
-bool ContinueSession(bool alt, const string& email, const string& user_token,
- const string& session_id, const Challenge& challenge,
- string* response);
-
-// Returns user information from the metadata server.
-bool GetUser(const string& username, string* response);
-} // namespace oslogin_utils
diff --git a/packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c b/packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c
deleted file mode 100644
index b1be6fc..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/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 <k@kev009.com>
- */
-
-#include <sys/param.h>
-
-#ifdef BSD
-
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-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/src/nss/nss_cache_oslogin.c b/packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c
deleted file mode 100644
index 55bb78d..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c
+++ /dev/null
@@ -1,274 +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 <sys/mman.h>
-
-// Locking implementation: use pthreads.
-#include <pthread.h>
-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;
-}
-
-//
-// Routines for passwd map defined below here
-//
-
-// _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) {
- enum nss_status ret;
-
- NSS_CACHE_OSLOGIN_LOCK();
- 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) {
- enum nss_status ret;
-
- NSS_CACHE_OSLOGIN_LOCK();
- 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;
- }
- }
-
- _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/src/nss/nss_oslogin.cc b/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
deleted file mode 100644
index 2a34c83..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2017 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 <compat.h>
-#include <curl/curl.h>
-#include <errno.h>
-#include <grp.h>
-#include <nss.h>
-#include <oslogin_utils.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <iostream>
-#include <sstream>
-#include <string>
-
-using std::string;
-
-using oslogin_utils::AddUsersToGroup;
-using oslogin_utils::BufferManager;
-using oslogin_utils::FindGroup;
-using oslogin_utils::GetGroupsForUser;
-using oslogin_utils::GetUsersForGroup;
-using oslogin_utils::Group;
-using oslogin_utils::HttpGet;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::MutexLock;
-using oslogin_utils::NssCache;
-using oslogin_utils::ParseJsonToPasswd;
-using oslogin_utils::UrlEncode;
-
-// Size of the NssCache. This also determines how many users will be requested
-// per HTTP call.
-static const uint64_t kNssCacheSize = 2048;
-
-// NssCache for storing passwd entries.
-static NssCache nss_cache(kNssCacheSize);
-
-// Protects access to nss_cache.
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-extern "C" {
-
-// Get a passwd entry by id.
-enum nss_status _nss_oslogin_getpwuid_r(uid_t uid, struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- BufferManager buffer_manager(buffer, buflen);
- std::stringstream url;
- url << kMetadataServerUrl << "users?uid=" << uid;
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = ENOENT;
- return NSS_STATUS_NOTFOUND;
- }
- if (!ParseJsonToPasswd(response, result, &buffer_manager, errnop)) {
- if (*errnop == EINVAL) {
- openlog("nss_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Received malformed response from server: %s",
- response.c_str());
- closelog();
- }
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-// Get a passwd entry by name.
-enum nss_status _nss_oslogin_getpwnam_r(const char *name, struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- BufferManager buffer_manager(buffer, buflen);
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(name);
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = ENOENT;
- return NSS_STATUS_NOTFOUND;
- }
- if (!ParseJsonToPasswd(response, result, &buffer_manager, errnop)) {
- if (*errnop == EINVAL) {
- openlog("nss_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Received malformed response from server: %s",
- response.c_str());
- closelog();
- }
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status _nss_oslogin_getgrby(struct group *grp, char *buf,
- size_t buflen, int *errnop) {
- BufferManager buffer_manager(buf, buflen);
- if (!FindGroup(grp, &buffer_manager, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- std::vector<string> users;
- if (!GetUsersForGroup(grp->gr_name, &users, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- if (!AddUsersToGroup(users, grp, &buffer_manager, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status _nss_oslogin_getgrgid_r(gid_t gid, struct group *grp, char *buf,
- size_t buflen, int *errnop) {
- grp->gr_gid = gid;
- return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
-}
-
-enum nss_status _nss_oslogin_getgrnam_r(const char *name, struct group *grp,
- char *buf, size_t buflen, int *errnop) {
- grp->gr_name = (char *)name;
- return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
-}
-
-enum nss_status _nss_oslogin_initgroups_dyn(const char *user, gid_t skipgroup,
- long int *start, long int *size,
- gid_t **groupsp, long int limit,
- int *errnop) {
- std::vector<Group> grouplist;
- if (!GetGroupsForUser(string(user), &grouplist, errnop)) {
- return NSS_STATUS_NOTFOUND;
- }
-
- gid_t *groups = *groupsp;
- for (int i = 0; i < (int) grouplist.size(); i++) {
- // Resize the buffer if needed.
- if (*start == *size) {
- gid_t *newgroups;
- long int newsize = 2 * *size;
- // Stop at limit if provided.
- if (limit > 0) {
- if (*size >= limit) {
- *errnop = ERANGE;
- return NSS_STATUS_TRYAGAIN;
- }
- newsize = MIN(limit, newsize);
- }
- newgroups = (gid_t *)realloc(groups, newsize * sizeof(gid_t *));
- if (newgroups == NULL) {
- *errnop = EAGAIN;
- return NSS_STATUS_TRYAGAIN;
- }
- *groupsp = groups = newgroups;
- *size = newsize;
- }
- groups[(*start)++] = grouplist[i].gid;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-// nss_getpwent_r() is intentionally left unimplemented. This functionality is
-// now covered by the nss_cache binary and nss_cache module.
-
-nss_status _nss_oslogin_getpwent_r() { return NSS_STATUS_NOTFOUND; }
-nss_status _nss_oslogin_endpwent() { return NSS_STATUS_SUCCESS; }
-nss_status _nss_oslogin_setpwent() { return NSS_STATUS_SUCCESS; }
-
-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);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
-
-DECLARE_NSS_METHOD_TABLE(methods,
- {NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r,
- (void *)_nss_oslogin_getpwnam_r},
- {NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r,
- (void *)_nss_oslogin_getpwuid_r},
- {NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r,
- (void *)_nss_oslogin_getpwent_r},
- {NSDB_PASSWD, "endpwent", __nss_compat_endpwent,
- (void *)_nss_oslogin_endpwent},
- {NSDB_PASSWD, "setpwent", __nss_compat_setpwent,
- (void *)_nss_oslogin_setpwent},
- {NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r,
- (void *)_nss_oslogin_getgrnam_r},
- {NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r,
- (void *)_nss_oslogin_getgrgid_r}, )
-
-NSS_REGISTER_METHODS(methods)
-} // extern "C"
diff --git a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc b/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc
deleted file mode 100644
index 27abe53..0000000
--- a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 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.
-
-#define PAM_SM_ACCOUNT
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using std::string;
-
-using oslogin_utils::HttpGet;
-using oslogin_utils::GetUser;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::ValidateUserName;
-
-static const char kSudoersDir[] = "/var/google-sudoers.d/";
-
-extern "C" {
-
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
- const char **argv) {
- // The return value for this module should generally be ignored. By default we
- // will return PAM_SUCCESS.
- int pam_result = PAM_SUCCESS;
- const char *user_name;
- if ((pam_result = pam_get_user(pamh, &user_name, NULL)) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return pam_result;
- }
-
- if (!ValidateUserName(user_name)) {
- // If the user name is not a valid oslogin user, don't bother continuing.
- return PAM_SUCCESS;
- }
-
- string response;
- if (!GetUser(user_name, &response)) {
- return PAM_SUCCESS;
- }
-
- string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_SUCCESS;
- }
-
- std::stringstream url;
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=adminLogin";
-
- string filename = kSudoersDir;
- filename.append(user_name);
- struct stat buffer;
- bool file_exists = !stat(filename.c_str(), &buffer);
- long http_code;
- if (HttpGet(url.str(), &response, &http_code) && http_code == 200 &&
- ParseJsonToSuccess(response)) {
- if (!file_exists) {
- PAM_SYSLOG(pamh, LOG_INFO,
- "Granting sudo permissions to organization user %s.",
- user_name);
- std::ofstream sudoers_file;
- sudoers_file.open(filename.c_str());
- sudoers_file << user_name << " ALL=(ALL) NOPASSWD: ALL"
- << "\n";
- sudoers_file.close();
- chown(filename.c_str(), 0, 0);
- chmod(filename.c_str(), S_IRUSR | S_IRGRP);
- }
- } else if (file_exists) {
- remove(filename.c_str());
- }
- return pam_result;
-}
-}
diff --git a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc b/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc
deleted file mode 100644
index 8ddec7b..0000000
--- a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2017 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.
-
-#define PAM_SM_ACCOUNT
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-#include <map>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using oslogin_utils::ContinueSession;
-using oslogin_utils::GetUser;
-using oslogin_utils::HttpGet;
-using oslogin_utils::HttpPost;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::ParseJsonToChallenges;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::StartSession;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::ValidateUserName;
-
-static const char kUsersDir[] = "/var/google-users.d/";
-
-extern "C" {
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
- const char **argv) {
- const char *user_name;
- if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return PAM_AUTH_ERR;
- }
-
- if (!ValidateUserName(user_name)) {
- // Not a valid OS Login username.
- return PAM_IGNORE;
- }
-
- std::string users_filename = kUsersDir;
- users_filename.append(user_name);
- struct stat buffer;
- bool file_exists = !stat(users_filename.c_str(), &buffer);
-
- std::string str_user_name(user_name);
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(str_user_name);
-
- std::string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || response.empty() ||
- http_code != 200) {
- if (http_code == 404) {
- // This module is only consulted for OS Login users.
- return PAM_IGNORE;
- }
-
- // Check local file for that user as a last resort.
- if (file_exists) {
- return PAM_PERM_DENIED;
- }
-
- // We can't confirm this is an OS Login user, ignore module.
- return PAM_IGNORE;
- }
-
- std::string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_AUTH_ERR;
- }
-
- url.str("");
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=login";
- if (HttpGet(url.str(), &response, &http_code) && http_code == 200 &&
- ParseJsonToSuccess(response)) {
- if (!file_exists) {
- std::ofstream users_file(users_filename.c_str());
- chown(users_filename.c_str(), 0, 0);
- chmod(users_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP);
- }
- PAM_SYSLOG(pamh, LOG_INFO,
- "Organization user %s has login permission.",
- user_name);
- return PAM_SUCCESS;
- } else {
- if (file_exists) {
- remove(users_filename.c_str());
- }
- PAM_SYSLOG(pamh, LOG_INFO,
- "Organization user %s does not have login permission.",
- user_name);
-
- return PAM_PERM_DENIED;
- }
-}
-
-PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc,
- const char **argv) {
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags,
- int argc, const char **argv)
-{
- const char* user_name;
- if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return PAM_PERM_DENIED;
- }
-
- std::string str_user_name(user_name);
- if (!ValidateUserName(user_name)) {
- return PAM_PERM_DENIED;
- }
-
- std::string response;
- if (!(GetUser(str_user_name, &response))) {
- return PAM_PERM_DENIED;
- }
-
- // System accounts begin with the prefix `sa_`.
- std::string sa_prefix = "sa_";
- if (str_user_name.compare(0, sa_prefix.size(), sa_prefix) == 0) {
- return PAM_SUCCESS;
- }
-
- std::string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_PERM_DENIED;
- }
-
- response = "";
- if (!StartSession(email, &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from the two-factor start session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
-
- std::string status;
- if (!ParseJsonToKey(response, "status", &status)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Failed to parse status from start session response");
- return PAM_PERM_DENIED;
- }
-
- if (status == "NO_AVAILABLE_CHALLENGES") {
- return PAM_SUCCESS; // User is not two-factor enabled.
- }
-
- std::string session_id;
- if (!ParseJsonToKey(response, "sessionId", &session_id)) {
- return PAM_PERM_DENIED;
- }
-
- std::vector<oslogin_utils::Challenge> challenges;
- if (!ParseJsonToChallenges(response, &challenges)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Failed to parse challenge values from JSON response");
- return PAM_PERM_DENIED;
- }
-
- std::map<std::string,std::string> user_prompts;
- user_prompts[AUTHZEN] = "Google phone prompt";
- user_prompts[TOTP] = "Security code from Google Authenticator application";
- user_prompts[INTERNAL_TWO_FACTOR] = "Security code from security key";
- user_prompts[IDV_PREREGISTERED_PHONE] =
- "Voice or text message verification code";
-
- oslogin_utils::Challenge challenge;
- if (challenges.size() > 1) {
- std::stringstream prompt;
- prompt << "Available authentication methods: ";
- for(vector<oslogin_utils::Challenge>::size_type i = 0;
- i != challenges.size(); ++i)
- prompt << "\n" << i+1 << ": " << user_prompts[challenges[i].type];
- prompt << "\n\nEnter a number: ";
-
- char *choice = NULL;
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &choice, "%s",
- prompt.str().c_str()) != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
-
- int choicei;
- if (sscanf(choice, "%d", &choicei) == EOF) {
- pam_error(pamh, "Unable to get user input");
- }
- if (choicei > challenges.size()) {
- pam_error(pamh, "Invalid option");
- }
- challenge = challenges[choicei - 1];
- } else {
- challenge = challenges[0];
- }
-
- if (challenge.status != "READY") {
- // Call continueSession with the START_ALTERNATE flag.
- if (!ContinueSession(true, email, "", session_id, challenge, &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from two-factor continue session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
- }
-
- char* user_token = NULL;
- if (challenge.type == INTERNAL_TWO_FACTOR) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "Enter your security code: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == TOTP) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "Enter your one-time password: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == AUTHZEN) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "A login prompt has been sent to your enrolled device. "
- "Press enter to continue") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == IDV_PREREGISTERED_PHONE) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "A security code has been sent to your phone. "
- "Enter code to continue: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else {
- PAM_SYSLOG(pamh, LOG_ERR, "Unsupported challenge type %s",
- challenge.type.c_str());
- return PAM_PERM_DENIED;
- }
-
- if (!ContinueSession(false, email, user_token, session_id, challenge,
- &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from two-factor continue session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
-
- if (!ParseJsonToKey(response, "status", &status)
- || status != "AUTHENTICATED") {
- return PAM_PERM_DENIED;
- }
-
- return PAM_SUCCESS;
-}
-}
diff --git a/packages/google-compute-engine-oslogin/src/utils.cc b/packages/google-compute-engine-oslogin/src/utils.cc
deleted file mode 100644
index 0f05f6f..0000000
--- a/packages/google-compute-engine-oslogin/src/utils.cc
+++ /dev/null
@@ -1,864 +0,0 @@
-// Copyright 2017 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.
-
-// Requires libcurl4-openssl-dev libjson0 and libjson0-dev
-#include <curl/curl.h>
-#include <errno.h>
-#include <grp.h>
-#include <json.h>
-#include <nss.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <cstring>
-#include <iostream>
-#include <sstream>
-
-#if defined(__clang__) || __GNUC__ > 4 || \
- (__GNUC__ == 4 && \
- (__GNUC_MINOR__ > 9 || (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 0)))
-#include <regex>
-#define Regex std
-#else
-#include <boost/regex.hpp>
-#define Regex boost
-#endif
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using std::string;
-
-// Maximum number of retries for HTTP requests.
-const int kMaxRetries = 1;
-
-// Regex for validating user names.
-const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$";
-
-namespace oslogin_utils {
-
-BufferManager::BufferManager(char* buf, size_t buflen)
- : buf_(buf), buflen_(buflen) {}
-
-bool BufferManager::AppendString(const string& value, char** buffer,
- int* errnop) {
- size_t bytes_to_write = value.length() + 1;
- *buffer = static_cast<char*>(Reserve(bytes_to_write, errnop));
- if (*buffer == NULL) {
- return false;
- }
- strncpy(*buffer, value.c_str(), bytes_to_write);
- return true;
-}
-
-bool BufferManager::CheckSpaceAvailable(size_t bytes_to_write) const {
- if (bytes_to_write > buflen_) {
- return false;
- }
- return true;
-}
-
-void* BufferManager::Reserve(size_t bytes, int* errnop) {
- if (!CheckSpaceAvailable(bytes)) {
- *errnop = ERANGE;
- return NULL;
- }
- void* result = buf_;
- buf_ += bytes;
- buflen_ -= bytes;
- return result;
-}
-
-NssCache::NssCache(int cache_size)
- : cache_size_(cache_size),
- passwd_cache_(cache_size),
- page_token_(""),
- on_last_page_(false) {}
-
-void NssCache::Reset() {
- page_token_ = "";
- index_ = 0;
- passwd_cache_.clear();
- on_last_page_ = false;
-}
-
-bool NssCache::HasNextPasswd() {
- return (index_ < passwd_cache_.size()) && !passwd_cache_[index_].empty();
-}
-
-bool NssCache::GetNextPasswd(BufferManager* buf, passwd* result, int* errnop) {
- if (!HasNextPasswd()) {
- *errnop = ENOENT;
- return false;
- }
- string cached_passwd = passwd_cache_[index_];
- bool success = ParseJsonToPasswd(cached_passwd, result, buf, errnop);
- if (success) {
- index_++;
- }
- return success;
-}
-
-bool NssCache::LoadJsonArrayToCache(string response) {
- Reset();
- json_object* root = NULL;
- root = json_tokener_parse(response.c_str());
- if (root == NULL) {
- return false;
- }
- // First grab the page token.
- json_object* page_token_object;
- if (json_object_object_get_ex(root, "nextPageToken", &page_token_object)) {
- page_token_ = json_object_get_string(page_token_object);
- } else {
- // If the page token is not found, assume something went wrong.
- page_token_ = "";
- on_last_page_ = true;
- return false;
- }
- // A page_token of 0 means we are done. This response will not contain any
- // login profiles.
- if (page_token_ == "0") {
- page_token_ = "";
- on_last_page_ = true;
- return false;
- }
- // Now grab all of the loginProfiles.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- page_token_ = "";
- return false;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- int arraylen = json_object_array_length(login_profiles);
- if (arraylen == 0 || arraylen > cache_size_) {
- page_token_ = "";
- return false;
- }
- for (int i = 0; i < arraylen; i++) {
- json_object* profile = json_object_array_get_idx(login_profiles, i);
- passwd_cache_.push_back(
- json_object_to_json_string_ext(profile, JSON_C_TO_STRING_PLAIN));
- }
- return true;
-}
-
-bool NssCache::NssGetpwentHelper(BufferManager* buf, struct passwd* result,
- int* errnop) {
- if (!HasNextPasswd() && !OnLastPage()) {
- std::stringstream url;
- url << kMetadataServerUrl << "users?pagesize=" << cache_size_;
- string page_token = GetPageToken();
- if (!page_token.empty()) {
- url << "&pagetoken=" << page_token;
- }
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty() || !LoadJsonArrayToCache(response)) {
- // It is possible this to be true after LoadJsonArrayToCache(), so we
- // must check it again.
- if (!OnLastPage()) {
- *errnop = ENOENT;
- }
- return false;
- }
- }
- if (HasNextPasswd() && !GetNextPasswd(buf, result, errnop)) {
- return false;
- }
- return true;
-}
-
-size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp) {
- if (userp) {
- std::ostream& os = *static_cast<std::ostream*>(userp);
- std::streamsize len = size * nmemb;
- if (os.write(static_cast<char*>(buf), len)) {
- return len;
- }
- }
- return 0;
-}
-
-bool HttpDo(const string& url, const string& data, string* response,
- long* http_code) {
- if (response == NULL || http_code == NULL) {
- return false;
- }
- CURLcode code(CURLE_FAILED_INIT);
- curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL);
- CURL* curl = curl_easy_init();
- std::ostringstream response_stream;
- int retry_count = 0;
- if (curl) {
- struct curl_slist* header_list = NULL;
- header_list = curl_slist_append(header_list, "Metadata-Flavor: Google");
- if (header_list == NULL) {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return false;
- }
- do {
- response_stream.str("");
- response_stream.clear();
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &OnCurlWrite);
- curl_easy_setopt(curl, CURLOPT_FILE, &response_stream);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- if (data != "") {
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
- }
-
- code = curl_easy_perform(curl);
- if (code != CURLE_OK) {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return false;
- }
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code);
- } while (retry_count++ < kMaxRetries && *http_code == 500);
- curl_slist_free_all(header_list);
- }
- *response = response_stream.str();
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return true;
-}
-
-bool HttpGet(const string& url, string* response, long* http_code) {
- return HttpDo(url, "", response, http_code);
-}
-
-bool HttpPost(const string& url, const string& data, string* response,
- long* http_code) {
- return HttpDo(url, data, response, http_code);
-}
-
-bool ValidateUserName(const string& user_name) {
- Regex::regex r(kUserNameRegex);
- return Regex::regex_match(user_name, r);
-}
-
-string UrlEncode(const string& param) {
- CURL* curl = curl_easy_init();
- char* encoded = curl_easy_escape(curl, param.c_str(), param.length());
- if (encoded == NULL) {
- curl_easy_cleanup(curl);
- return "";
- }
- string encoded_param = encoded;
- curl_free(encoded);
- curl_easy_cleanup(curl);
- return encoded_param;
-}
-
-bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop) {
- // OS Login disallows uids less than 1000.
- if (result->pw_uid < 1000) {
- *errnop = EINVAL;
- return false;
- }
- if (result->pw_gid == 0) {
- *errnop = EINVAL;
- return false;
- }
- if (strlen(result->pw_name) == 0) {
- *errnop = EINVAL;
- return false;
- }
- if (strlen(result->pw_dir) == 0) {
- string home_dir = "/home/";
- home_dir.append(result->pw_name);
- if (!buf->AppendString(home_dir, &result->pw_dir, errnop)) {
- return false;
- }
- }
- if (strlen(result->pw_shell) == 0) {
- if (!buf->AppendString(DEFAULT_SHELL, &result->pw_shell, errnop)) {
- return false;
- }
- }
-
- // OS Login does not utilize the passwd field and reserves the gecos field.
- // Set these to be empty.
- if (!buf->AppendString("", &result->pw_gecos, errnop)) {
- return false;
- }
- if (!buf->AppendString("", &result->pw_passwd, errnop)) {
- return false;
- }
- return true;
-}
-
-bool ParseJsonToUsers(const string& json, std::vector<string>* result) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* users = NULL;
- if (!json_object_object_get_ex(root, "usernames", &users)) {
- return false;
- }
- if (json_object_get_type(users) != json_type_array) {
- return false;
- }
- for (int idx = 0; idx < json_object_array_length(users); idx++) {
- json_object* user = json_object_array_get_idx(users, idx);
- const char* username = json_object_get_string(user);
- result->push_back(string(username));
- }
- return true;
-}
-
-bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* groups = NULL;
- if (!json_object_object_get_ex(root, "posixGroups", &groups)) {
- return false;
- }
- if (json_object_get_type(groups) != json_type_array) {
- return false;
- }
- for (int idx = 0; idx < json_object_array_length(groups); idx++) {
- json_object* group = json_object_array_get_idx(groups, idx);
-
- json_object* gid;
- if (!json_object_object_get_ex(group, "gid", &gid)) {
- return false;
- }
-
- json_object* name;
- if (!json_object_object_get_ex(group, "name", &name)) {
- return false;
- }
-
- Group g;
- g.gid = json_object_get_int64(gid);
- // get_int64 will confusingly return 0 if the string can't be converted to
- // an integer. We can't rely on type check as it may be a string in the API.
- if (g.gid == 0) {
- return false;
- }
- g.name = json_object_get_string(name);
- if (g.name == "") {
- return false;
- }
-
- result->push_back(g);
- }
- return true;
-}
-
-std::vector<string> ParseJsonToSshKeys(const string& json) {
- std::vector<string> result;
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return result;
- }
- // Locate the sshPublicKeys object.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- return result;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return result;
- }
- login_profiles = json_object_array_get_idx(login_profiles, 0);
-
- json_object* ssh_public_keys = NULL;
- if (!json_object_object_get_ex(login_profiles, "sshPublicKeys",
- &ssh_public_keys)) {
- return result;
- }
-
- if (json_object_get_type(ssh_public_keys) != json_type_object) {
- return result;
- }
- json_object_object_foreach(ssh_public_keys, key, obj) {
- (void)(key);
- if (json_object_get_type(obj) != json_type_object) {
- continue;
- }
- string key_to_add = "";
- bool expired = false;
- json_object_object_foreach(obj, key, val) {
- string string_key(key);
- int val_type = json_object_get_type(val);
- if (string_key == "key") {
- if (val_type != json_type_string) {
- continue;
- }
- key_to_add = (char*)json_object_get_string(val);
- }
- if (string_key == "expirationTimeUsec") {
- if (val_type == json_type_int || val_type == json_type_string) {
- uint64_t expiry_usec = (uint64_t)json_object_get_int64(val);
- struct timeval tp;
- gettimeofday(&tp, NULL);
- uint64_t cur_usec = tp.tv_sec * 1000000 + tp.tv_usec;
- expired = cur_usec > expiry_usec;
- } else {
- continue;
- }
- }
- }
- if (!key_to_add.empty() && !expired) {
- result.push_back(key_to_add);
- }
- }
- return result;
-}
-
-bool ParseJsonToPasswd(const string& json, struct passwd* result,
- BufferManager* buf, int* errnop) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- *errnop = ENOENT;
- return false;
- }
- json_object* login_profiles = NULL;
- // If this is called from getpwent_r, loginProfiles won't be in the response.
- if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- root = login_profiles;
- root = json_object_array_get_idx(root, 0);
- }
- // Locate the posixAccounts object.
- json_object* posix_accounts = NULL;
- if (!json_object_object_get_ex(root, "posixAccounts", &posix_accounts)) {
- *errnop = ENOENT;
- return false;
- }
- if (json_object_get_type(posix_accounts) != json_type_array) {
- return false;
- }
- posix_accounts = json_object_array_get_idx(posix_accounts, 0);
-
- // Populate with some default values that ValidatePasswd can detect if they
- // are not set.
- result->pw_uid = 0;
- result->pw_shell = (char*)"";
- result->pw_name = (char*)"";
- result->pw_dir = (char*)"";
-
- // Iterate through the json response and populate the passwd struct.
- if (json_object_get_type(posix_accounts) != json_type_object) {
- return false;
- }
- json_object_object_foreach(posix_accounts, key, val) {
- int val_type = json_object_get_type(val);
- // Convert char* to c++ string for easier comparison.
- string string_key(key);
-
- if (string_key == "uid") {
- if (val_type == json_type_int || val_type == json_type_string) {
- result->pw_uid = (uint32_t)json_object_get_int64(val);
- if (result->pw_uid == 0) {
- *errnop = EINVAL;
- return false;
- }
- } else {
- *errnop = EINVAL;
- return false;
- }
- } else if (string_key == "gid") {
- if (val_type == json_type_int || val_type == json_type_string) {
- result->pw_gid = (uint32_t)json_object_get_int64(val);
- // Use the uid as the default group when gid is not set or is zero.
- if (result->pw_gid == 0) {
- result->pw_gid = result->pw_uid;
- }
- } else {
- *errnop = EINVAL;
- return false;
- }
- } else if (string_key == "username") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_name, errnop)) {
- return false;
- }
- } else if (string_key == "homeDirectory") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_dir, errnop)) {
- return false;
- }
- } else if (string_key == "shell") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_shell, errnop)) {
- return false;
- }
- }
- }
-
- return ValidatePasswd(result, buf, errnop);
-}
-
-bool AddUsersToGroup(std::vector<string> users, struct group* result,
- BufferManager* buf, int* errnop) {
- if (users.size() < 1) {
- return true;
- }
-
- // Get some space for the char* array for number of users + 1 for NULL cap.
- char** bufp;
- if (!(bufp =
- (char**)buf->Reserve(sizeof(char*) * (users.size() + 1), errnop))) {
- return false;
- }
- result->gr_mem = bufp;
-
- for (int i = 0; i < (int) users.size(); i++) {
- if (!buf->AppendString(users[i], bufp, errnop)) {
- result->gr_mem = NULL;
- return false;
- }
- }
- *bufp = NULL; // End the array with a null pointer.
-
- return true;
-}
-
-bool ParseJsonToEmail(const string& json, string* email) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
- // Locate the email object.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- return false;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- login_profiles = json_object_array_get_idx(login_profiles, 0);
- json_object* json_email = NULL;
- if (!json_object_object_get_ex(login_profiles, "name", &json_email)) {
- return false;
- }
-
- *email = json_object_get_string(json_email);
- return true;
-}
-
-bool ParseJsonToSuccess(const string& json) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
- json_object* success = NULL;
- if (!json_object_object_get_ex(root, "success", &success)) {
- return false;
- }
- return (bool)json_object_get_boolean(success);
-}
-
-bool ParseJsonToKey(const string& json, const string& key, string* response) {
- json_object* root = NULL;
- json_object* json_response = NULL;
- const char* c_response;
-
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- if (!json_object_object_get_ex(root, key.c_str(), &json_response)) {
- return false;
- }
-
- if (!(c_response = json_object_get_string(json_response))) {
- return false;
- }
-
- *response = c_response;
- return true;
-}
-
-bool ParseJsonToChallenges(const string& json,
- std::vector<Challenge>* challenges) {
- json_object* root = NULL;
-
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* jsonChallenges = NULL;
- if (!json_object_object_get_ex(root, "challenges", &jsonChallenges)) {
- return false;
- }
-
- json_object *challengeId, *challengeType, *challengeStatus = NULL;
- for (int i = 0; i < json_object_array_length(jsonChallenges); ++i) {
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "challengeId", &challengeId)) {
- return false;
- }
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "challengeType", &challengeType)) {
- return false;
- }
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "status", &challengeStatus)) {
- return false;
- }
- Challenge challenge;
- challenge.id = json_object_get_int(challengeId);
- challenge.type = json_object_get_string(challengeType);
- challenge.status = json_object_get_string(challengeStatus);
-
- challenges->push_back(challenge);
- }
-
- return true;
-}
-
-bool FindGroup(struct group* result, BufferManager* buf, int* errnop) {
- if (result->gr_name == NULL && result->gr_gid == 0) {
- return false;
- }
- std::stringstream url;
- std::vector<Group> groups;
-
- string response;
- long http_code;
- string pageToken = "";
-
- do {
- url.str("");
- url << kMetadataServerUrl << "groups";
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
-
- if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
- pageToken = "";
- }
-
- groups.clear();
- if (!ParseJsonToGroups(response, &groups) || groups.empty()) {
- *errnop = ENOENT;
- return false;
- }
-
- // Check for a match.
- for (int i = 0; i < (int) groups.size(); i++) {
- Group el = groups[i];
- if ((result->gr_name != NULL) && (string(result->gr_name) == el.name)) {
- // Set the name even though it matches because the final string must
- // be stored in the provided buffer.
- if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
- return false;
- }
- result->gr_gid = el.gid;
- return true;
- }
- if ((result->gr_gid != 0) && (result->gr_gid == el.gid)) {
- if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
- return false;
- }
- return true;
- }
- }
- } while (pageToken != "");
- // Not found.
- *errnop = ENOENT;
- return false;
-}
-
-bool GetGroupsForUser(string username, std::vector<Group>* groups,
- int* errnop) {
- std::stringstream url;
-
- string response;
- long http_code;
- string pageToken = "";
-
- do {
- url.str("");
- url << kMetadataServerUrl << "groups?username=" << username;
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
-
- if (!ParseJsonToKey(response, "pageToken", &pageToken)) {
- pageToken = "";
- }
-
- if (!ParseJsonToGroups(response, groups)) {
- *errnop = ENOENT;
- return false;
- }
- } while (pageToken != "");
- return true;
-}
-
-bool GetUsersForGroup(string groupname, std::vector<string>* users,
- int* errnop) {
- string response;
- long http_code;
- string pageToken = "";
- std::stringstream url;
-
- do {
- url.str("");
- url << kMetadataServerUrl << "users?groupname=" << groupname;
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
- if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
- pageToken = "";
- }
- if (!ParseJsonToUsers(response, users)) {
- *errnop = EINVAL;
- return false;
- }
- } while (pageToken != "");
- return true;
-}
-
-bool GetUser(const string& username, string* response) {
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(username);
-
- long http_code = 0;
- if (!HttpGet(url.str(), response, &http_code) || response->empty() ||
- http_code != 200) {
- return false;
- }
- return true;
-}
-
-bool StartSession(const string& email, string* response) {
- bool ret = true;
- struct json_object *jobj, *jarr;
-
- jarr = json_object_new_array();
- json_object_array_add(jarr, json_object_new_string(INTERNAL_TWO_FACTOR));
- json_object_array_add(jarr, json_object_new_string(AUTHZEN));
- json_object_array_add(jarr, json_object_new_string(TOTP));
- json_object_array_add(jarr, json_object_new_string(IDV_PREREGISTERED_PHONE));
-
- jobj = json_object_new_object();
- json_object_object_add(jobj, "email", json_object_new_string(email.c_str()));
- json_object_object_add(jobj, "supportedChallengeTypes", jarr); // Ownership transferred to jobj.
-
- const char* data;
- data = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
-
- std::stringstream url;
- url << kMetadataServerUrl << "authenticate/sessions/start";
-
- long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
- http_code != 200) {
- ret = false;
- }
-
- json_object_put(jobj);
-
- return ret;
-}
-
-bool ContinueSession(bool alt, const string& email, const string& user_token,
- const string& session_id, const Challenge& challenge,
- string* response) {
- bool ret = true;
- struct json_object *jobj, *jresp;
-
- jobj = json_object_new_object();
- json_object_object_add(jobj, "email", json_object_new_string(email.c_str()));
- json_object_object_add(jobj, "challengeId",
- json_object_new_int(challenge.id));
-
- if (alt) {
- json_object_object_add(jobj, "action",
- json_object_new_string("START_ALTERNATE"));
- } else {
- json_object_object_add(jobj, "action", json_object_new_string("RESPOND"));
- }
-
- // AUTHZEN type and START_ALTERNATE action don't provide credentials.
- if (challenge.type != AUTHZEN && !alt) {
- jresp = json_object_new_object();
- json_object_object_add(jresp, "credential",
- json_object_new_string(user_token.c_str()));
- json_object_object_add(jobj, "proposalResponse", jresp); // Ownership transferred to jobj.
- }
-
- const char* data = NULL;
- data = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
-
- std::stringstream url;
- url << kMetadataServerUrl << "authenticate/sessions/" << session_id
- << "/continue";
- long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
- http_code != 200) {
- ret = false;
- }
-
- json_object_put(jobj);
-
- return ret;
-}
-} // namespace oslogin_utils