From 9f15b1c1407b01e28dcb066400eab3200ee4f850 Mon Sep 17 00:00:00 2001 From: Liam Hopkins Date: Wed, 7 Aug 2019 15:44:14 -0700 Subject: Move to new repo (#833) Move the OS Login components to new repo guest-oslogin, leaving a README. --- daisy_workflows/build_deb_packages.sh | 1 + daisy_workflows/build_el_packages.sh | 1 + packages/google-compute-engine-oslogin/Makefile | 19 - packages/google-compute-engine-oslogin/README.md | 222 +----- .../google_oslogin_control | 461 ----------- .../man/nss-cache-oslogin.8 | 48 -- .../man/nss-oslogin.8 | 41 - .../packaging/debian/changelog | 164 ---- .../packaging/debian/compat | 1 - .../packaging/debian/control | 13 - .../packaging/debian/copyright | 27 - .../packaging/debian/rules | 6 - .../packaging/debian/source/format | 1 - .../packaging/google-compute-engine-oslogin.spec | 101 --- .../packaging/setup_deb.sh | 54 -- .../packaging/setup_rpm.sh | 43 - .../google-compute-engine-oslogin/selinux/Makefile | 17 - .../selinux/README.md | 17 - .../selinux/oslogin.fc | 2 - .../selinux/oslogin.pp | Bin 1798 -> 0 bytes .../selinux/oslogin.te | 24 - .../google-compute-engine-oslogin/src/Makefile | 86 -- .../src/authorized_keys/authorized_keys.cc | 78 -- .../src/cache_refresh/cache_refresh.cc | 119 --- .../src/include/compat.h | 62 -- .../src/include/nss_cache_oslogin.h | 65 -- .../src/include/oslogin_utils.h | 238 ------ .../src/nss/compat/getpwent_r.c | 87 --- .../src/nss/nss_cache_oslogin.c | 274 ------- .../src/nss/nss_oslogin.cc | 209 ----- .../src/pam/pam_oslogin_admin.cc | 100 --- .../src/pam/pam_oslogin_login.cc | 273 ------- .../google-compute-engine-oslogin/src/utils.cc | 864 --------------------- .../google-compute-engine-oslogin/test/Makefile | 34 - .../test/oslogin_utils_test.cc | 627 --------------- 35 files changed, 4 insertions(+), 4375 deletions(-) delete mode 100644 packages/google-compute-engine-oslogin/Makefile delete mode 100644 packages/google-compute-engine-oslogin/google_oslogin_control delete mode 100644 packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8 delete mode 100644 packages/google-compute-engine-oslogin/man/nss-oslogin.8 delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/changelog delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/compat delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/control delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/copyright delete mode 100755 packages/google-compute-engine-oslogin/packaging/debian/rules delete mode 100644 packages/google-compute-engine-oslogin/packaging/debian/source/format delete mode 100644 packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec delete mode 100755 packages/google-compute-engine-oslogin/packaging/setup_deb.sh delete mode 100755 packages/google-compute-engine-oslogin/packaging/setup_rpm.sh delete mode 100644 packages/google-compute-engine-oslogin/selinux/Makefile delete mode 100644 packages/google-compute-engine-oslogin/selinux/README.md delete mode 100644 packages/google-compute-engine-oslogin/selinux/oslogin.fc delete mode 100644 packages/google-compute-engine-oslogin/selinux/oslogin.pp delete mode 100644 packages/google-compute-engine-oslogin/selinux/oslogin.te delete mode 100644 packages/google-compute-engine-oslogin/src/Makefile delete mode 100644 packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc delete mode 100644 packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc delete mode 100644 packages/google-compute-engine-oslogin/src/include/compat.h delete mode 100644 packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h delete mode 100644 packages/google-compute-engine-oslogin/src/include/oslogin_utils.h delete mode 100644 packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c delete mode 100644 packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c delete mode 100644 packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc delete mode 100644 packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc delete mode 100644 packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc delete mode 100644 packages/google-compute-engine-oslogin/src/utils.cc delete mode 100644 packages/google-compute-engine-oslogin/test/Makefile delete mode 100644 packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc diff --git a/daisy_workflows/build_deb_packages.sh b/daisy_workflows/build_deb_packages.sh index d877064..061b31d 100755 --- a/daisy_workflows/build_deb_packages.sh +++ b/daisy_workflows/build_deb_packages.sh @@ -43,6 +43,7 @@ fi # Build packages. cd compute-image-packages/packages for package in *; do + [[ -d "${package}/packaging" ]] || continue pushd "$package" ./packaging/setup_deb.sh if [[ $? -ne 0 ]]; then diff --git a/daisy_workflows/build_el_packages.sh b/daisy_workflows/build_el_packages.sh index d02f1ed..264f795 100755 --- a/daisy_workflows/build_el_packages.sh +++ b/daisy_workflows/build_el_packages.sh @@ -43,6 +43,7 @@ fi # Build packages. cd compute-image-packages/packages for package in *; do + [[ -d "${package}/packaging" ]] || continue pushd "$package" ./packaging/setup_rpm.sh if [[ $? -ne 0 ]]; then diff --git a/packages/google-compute-engine-oslogin/Makefile b/packages/google-compute-engine-oslogin/Makefile deleted file mode 100644 index b22c16f..0000000 --- a/packages/google-compute-engine-oslogin/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -all install : - $(MAKE) -C src $@ - -tests : - $(MAKE) -C test $@ - -clean : - $(MAKE) -C src clean - $(MAKE) -C test clean - -prowbuild : debian_deps all - -prowtest : debian_deps tests - -debian_deps : - sudo apt-get -y install g++ libcurl4-openssl-dev libjson-c-dev libpam-dev \ - googletest && touch $@ - -.PHONY : all clean install prowbuild prowtest diff --git a/packages/google-compute-engine-oslogin/README.md b/packages/google-compute-engine-oslogin/README.md index 4acc31e..0eb1804 100644 --- a/packages/google-compute-engine-oslogin/README.md +++ b/packages/google-compute-engine-oslogin/README.md @@ -1,222 +1,4 @@ ## OS Login Guest Environment for Google Compute Engine -This repository contains the system components responsible for providing Google -Cloud OS Login features on Google Compute Engine instances. - -**Table of Contents** - -* [Overview](#overview) -* [Components](#components) - * [Authorized Keys Command](#authorized-keys-command) - * [NSS Modules](#nss-modules) - * [PAM Modules](#pam-modules) -* [Utilities](#Utilities) - * [Control Script](#control-script) - * [SELinux Policy](#selinux-policy) -* [Source Packages](#source-packages) - * [DEB](#deb) - * [RPM](#rpm) - -## Overview - -The OS Login Guest Environment consists of the following main components: - -* **Authorized Keys Command** which provides SSH keys from the user's OS Login - profile to sshd for authenticating users at login. -* **NSS Modules** which provide support for making OS Login user and group - information available to the system, using NSS (Name Service Switch) - functionality. -* **PAM Modules** which provide authorization (and authentication if - two-factor support is enabled) support allowing the system to use Google - Cloud IAM permissions to control the ability to log into an instance or to - perform operations as root (via `sudo`). - -In addition to the main components, there are also the following utilities: - -* **google_oslogin_control** is a shell script for activating/deactivating the - OS Login components. -* **google_oslogin_nss_cache** is a utility for updating the local user and - group cache. -* **selinux** contains SELinux policy definition files and a compiled policy - package for configuring SELinux to support OS Login. - -The **packaging** directory also contains files used to generate `.deb` and -`.rpm` packages for the OS Login components. - -## Components - -#### Authorized Keys Command - -The `google_authorized_keys` binary is designed to be used with the sshd -`AuthorizedKeysCommand` option in [sshd_config(5)](https://linux.die.net/man/5/sshd_config). -It does the following: - -* Reads the user's profile information from the metadata server: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?username= - ``` -* Checks to make sure that the user is authorized to log in: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=&policy=login - ``` -* If the check is successful, returns the SSH keys associated with the user - for use by sshd. Otherwise, exits with an error code. - -#### NSS Modules - -`libnss_oslogin.so` and `libnss_cache_oslogin.so` are NSS service modules which -make OS Login users and groups available for use on the local system. The module -is activated by adding `oslogin` and `cache_oslogin` entries for services in -[nsswitch.conf(5)](https://linux.die.net/man/5/nsswitch.conf). - -* To return a list of all users, the NSS module queries: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?pagesize= - ``` -* To look up a user by username, the NSS module queries: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?username= - ``` -* To look up a user by UID, the NSS module queries: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?uid= - ``` - -#### PAM Modules - -`pam_oslogin_login.so` is a PAM module which determines whether a given user is -allowed to SSH into an instance. - -It is activated by adding an entry for the account group to the PAM service -config for sshd as: - ``` - account requisite pam_oslogin_login.so - ``` - -This module: - -* Retrieves the user's profile information from the metadata server: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?username= - ``` -* If the user does not have OS Login profile information it is passed on to - the system authentication modules to be processed as a local user. -* Otherwise, the module confirms whether the user has permissions to SSH into - the instance: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=&policy=login - ``` -* If the user is authorized, PAM returns a success message and SSH can - proceed. Otherwise, PAM returns a denied message and the SSH check will - fail. - -`pam_oslogin_admin.so` is a PAM module which determines whether a given user -should have admin (sudo) permissions on the instance. - -It is activated by adding an entry for the `account` group to the PAM service -config for sshd config as: - ``` - account optional pam_oslogin_admin.so - ``` - -This module: - -* Retrieves the user's profile information from the metadata server. - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/users?username= - ``` -* If the user is not an OS Login user (a local user account), the module - returns success. -* Otherwise, the module determines if the user has admin permissions: - ``` - http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=&policy=adminLogin - ``` -* If the user is authorized as an admin, a file with the username is added to - `/var/google-sudoers.d/`. The file gives the user sudo privileges. -* If the authorization check fails for admin permissions, the file is removed - from `/var/google-sudoers.d/` if it exists. - -## Utilities - -#### Control Script - -The `google_oslogin_control` shell script activates or deactivates the OS Login -features. It is invoked by the google accounts daemon. The control file performs -the following tasks: - -* Adds (or removes) AuthorizedKeysCommand and AuthorizedKeysCommandUser lines - to (from) `sshd_config` and restarts sshd. -* Adds (or removes) `oslogin` and `cache_oslogin` to (from) `nsswitch.conf`. -* Adds (or removes) the `account` entries to (from) the PAM sshd config. Also - adds (or removes) the `pam_mkhomedir.so` module to automatically create the - home directory for an OS Login user. -* Creates (or deletes) the `/var/google-sudoers.d/` directory, and a file - called `google-oslogin` in `/etc/sudoers.d/` that includes the directory. - -#### SELinux Policy - -The `selinux` directory contains `.te` (type enforcement) and `.fc` (file -context) files used by SELinux to give the OS Login features the appropriate -SELinux permissions. These are compiled using `checkmodule` and -`semodule_package` to create an policy package `oslogin.pp`. - -## Source Packages - -There is currently support for creating packages for the following distros: - -* Debian 9 -* CentOS/RHEL 6 -* CentOS/RHEL 7 - -Files for these packages are in the `packaging/` directory. - -#### DEB - -_Note: the `packaging/setup_deb.sh` script performs these steps, but is not -production quality._ - -1. Install build dependencies: - ``` - sudo apt-get -y install make g++ libcurl4-openssl-dev libjson-c-dev libpam-dev - ``` -1. Install deb creation tools: - ``` - sudo apt-get -y install debhelper devscripts build-essential - ``` -1. Create a compressed tar file named - `google-compute-engine-oslogin_M.M.R.orig.tar.gz` using the files in this - directory, excluding the `packaging` directory (where M.M.R is the version - number). -1. In a separate directory, extract the `.orig.tar.gz` file and copy the - `debian` directory into the top level. -1. To build the package, run the command - ``` - debuild -us -uc - ``` - -#### RPM - -_Note: the `packaging/setup_rpm.sh` script performs these steps, but is not -production quality._ - -1. Install build dependencies: - ``` - sudo yum -y install make gcc-c++ libcurl-devel json-c json-c-devel pam-devel policycoreutils-python - ``` -1. Install rpm creation tools: - ``` - sudo yum -y install rpmdevtools - ``` -1. Create a compressed tar file named - `google-compute-engine-oslogin_M.M.R.orig.tar.gz` using the files in this - directory, excluding the `packaging` directory (where M.M.R is the version - number). -1. In a separate location, create a directory called `rpmbuild` and a - subdirectory called `SOURCES`. Copy the `.orig.tar.gz` file into the - `SOURCES` directory. -1. Copy the `SPECS` directory from the `rpmbuild` directory here into the - `rpmbuild` directory you created. -1. To build the package, run the command: - ``` - rpmbuild --define "_topdir /path/to/rpmbuild" -ba /path/to/rpmbuild/SPECS/google-compute-engine-oslogin.spec - ``` +**This package has moved. The OS Login on-guest components are now located in +the [guest-oslogin](https://github.com/GoogleCloudPlatform/guest-oslogin) repo** diff --git a/packages/google-compute-engine-oslogin/google_oslogin_control b/packages/google-compute-engine-oslogin/google_oslogin_control deleted file mode 100644 index bc85a8e..0000000 --- a/packages/google-compute-engine-oslogin/google_oslogin_control +++ /dev/null @@ -1,461 +0,0 @@ -#!/bin/sh -# 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. - -is_freebsd() { - [ "$(uname)" = "FreeBSD" ] - return $? -} - -nss_config="/etc/nsswitch.conf" -pam_sshd_config="/etc/pam.d/sshd" -pam_su_config="/etc/pam.d/su" -sshd_config="/etc/ssh/sshd_config" -group_config="/etc/security/group.conf" -sudoers_dir="/var/google-sudoers.d" -users_dir="/var/google-users.d" -added_comment="# Added by Google Compute Engine OS Login." -sshd_block="#### Google OS Login control. Do not edit this section. ####" -sshd_end_block="#### End Google OS Login control section. ####" -sudoers_file="/etc/sudoers.d/google-oslogin" -if is_freebsd; then - sudoers_file="/usr/local/etc/sudoers.d/google-oslogin" -fi - -# Update nsswitch.conf to include OS Login NSS module for passwd. -modify_nsswitch_conf() { - local nss_config="${1:-${nss_config}}" - - if ! grep -q '^passwd:.*oslogin' "$nss_config"; then - $sed -i"" '/^passwd:/ s/$/ cache_oslogin oslogin/' "$nss_config" - fi - - if is_freebsd && grep -q '^passwd:.*compat' "$nss_config"; then - $sed -i"" '/^passwd:/ s/compat/files/' "$nss_config" - fi -} - -restore_nsswitch_conf() { - local nss_config="${1:-${nss_config}}" - - $sed -i"" '/^passwd:/ s/ cache_oslogin oslogin//' "$nss_config" - if is_freebsd; then - $sed -i"" '/^passwd:/ s/files/compat/' "$nss_config" - fi -} - -modify_sshd_conf() ( - set -e - - local sshd_config="${1:-${sshd_config}}" - - local sshd_auth_keys_command="AuthorizedKeysCommand /usr/bin/google_authorized_keys" - local sshd_auth_keys_command_user="AuthorizedKeysCommandUser root" - local sshd_auth_methods="AuthenticationMethods publickey,keyboard-interactive" - local sshd_challenge="ChallengeResponseAuthentication yes" - - # Update google_authorized_keys path in FreeBSD. - if is_freebsd; then - sshd_auth_keys_command="AuthorizedKeysCommand /usr/local/bin/google_authorized_keys" - fi - - # Update directives for EL 6. - if grep -qs "release 6" /etc/redhat-release; then - sshd_auth_keys_command_user="AuthorizedKeysCommandRunAs root" - sshd_auth_methods="RequiredAuthentications2 publickey,keyboard-interactive" - fi - - add_or_update_sshd() { - local entry="$1" - local sshd_config="$2" - local directive="$(echo "$entry" | cut -d' ' -f1)" - local value="$(echo "$entry" | cut -d' ' -f2-)" - - # Check if directive is present. - if grep -Eq "^\s*${directive}" "$sshd_config"; then - # Check if value is incorrect. - if ! grep -Eq "^\s*${directive}(\s|=)+${value}" "$sshd_config"; then - # Comment out the line (because sshd_config is first-directive-found) - # and add to end section. - $sed -i"" -E "/^\s*${directive}/ s/^/${added_comment}\n#/" "$sshd_config" - $sed -i"" "/$sshd_end_block/ i${entry}" "$sshd_config" - fi - else - $sed -i"" "/$sshd_end_block/ i${entry}" "$sshd_config" - fi - } - - # Setup Google config block. - if ! grep -q "$sshd_block" "$sshd_config"; then - # Remove old-style additions. - $sed -i"" "/${added_comment}/,+1d" "$sshd_config" - printf "\n\n${sshd_block}\n${sshd_end_block}" >> "$sshd_config" - fi - - for entry in "$sshd_auth_keys_command" "$sshd_auth_keys_command_user"; do - add_or_update_sshd "$entry" "$sshd_config" - done - - if [ -n "$two_factor" ]; then - for entry in "$sshd_auth_methods" "$sshd_challenge"; do - add_or_update_sshd "$entry" "$sshd_config" - done - fi -) - -restore_sshd_conf() { - local sshd_config="${1:-${sshd_config}}" - - if ! grep -q "$sshd_block" "$sshd_config"; then - # Remove old-style additions. - $sed -i"" "/${added_comment}/,+1d" "$sshd_config" - else - # Uncomment commented-out fields and remove Google config block. - $sed -i"" "/${added_comment}/{n;s/^#//}" "$sshd_config" - $sed -i"" "/${added_comment}/d" "$sshd_config" - $sed -i"" "/${sshd_block}/,/${sshd_end_block}/d" "$sshd_config" - fi -} - -# Inserts pam modules to relevant pam stacks if missing. -modify_pam_config() ( - # TODO: idempotency of this function would be better assured if it wiped out - # and applied desired changes each time rather than detecting deltas. - - set -e - - local pam_sshd_config="${1:-${pam_sshd_config}}" - local pam_su_config="${1:-${pam_su_config}}" - - local pam_auth_oslogin="auth [success=done perm_denied=die default=ignore] pam_oslogin_login.so" - local pam_auth_group="auth [default=ignore] pam_group.so" - local pam_account_oslogin="account [success=ok default=ignore] pam_oslogin_admin.so" - local pam_account_admin="account [success=ok ignore=ignore default=die] pam_oslogin_login.so" - local pam_session_homedir="session [success=ok default=ignore] pam_mkhomedir.so" - local pam_account_su="account [success=bad ignore=ignore] pam_oslogin_login.so" - - # In FreeBSD, the used flags are not supported, replacing them with the - # previous ones (requisite and optional). This is not an exact feature parity - # with Linux. - if is_freebsd; then - pam_auth_oslogin="auth optional pam_oslogin_login.so" - pam_auth_group="auth optional pam_group.so" - pam_account_oslogin="account optional pam_oslogin_admin.so" - pam_account_admin="account requisite pam_oslogin_login.so" - pam_session_homedir="session optional pam_mkhomedir.so" - fi - - local added_config="" - local added_su_config="" - - # For COS this file is solely includes, so simply prepend the new config, - # making each entry the top of its stack. - if [ -e /etc/os-release ] && grep -q "ID=cos" /etc/os-release; then - added_config="${added_comment}\n" - for cfg in "$pam_account_admin" "$pam_account_oslogin" \ - "$pam_session_homedir" "$pam_auth_group"; do - grep -qE "^${cfg%% *}.*${cfg##* }" ${pam_sshd_config} || added_config="${added_config}${cfg}\n" - done - - if [ -n "$two_factor" ]; then - grep -q "$pam_auth_oslogin" "$pam_sshd_config" || added_config="${added_config}${pam_auth_oslogin}\n" - fi - - $sed -i"" "1i ${added_config}\n\n" "$pam_sshd_config" - - added_su_config="${added_comment}\n${pam_account_su}" - $sed -i"" "1i ${added_su_config}" "$pam_su_config" - - return 0 - fi - - # Find the distro-specific insertion point for auth and su. - if [ -e /etc/debian_version ]; then - # Get location of common-auth and check if preceding line is a comment. - insert=$($sed -rn "/^@include\s+common-auth/=" "$pam_sshd_config") - $sed -n "$((insert-1))p" "$pam_sshd_config" | grep -q '^#' && insert=$((insert-1)) - su_insert=$($sed -rn "/^@include\s+common-account/=" "$pam_su_config") - elif [ -e /etc/redhat-release ]; then - # Get location of password-auth. - insert=$($sed -rn "/^auth\s+(substack|include)\s+password-auth/=" \ - "$pam_sshd_config") - # Get location of system-auth. - su_insert=$($sed -rn "/^account\s+include\s+system-auth/=" "$pam_su_config") - elif [ -e /etc/os-release ] && grep -q 'ID="sles"' /etc/os-release; then - # Get location of common-auth. - insert=$($sed -rn "/^auth\s+include\s+common-auth/=" "$pam_sshd_config") - # Get location of common-account. - su_insert=$($sed -rn "/^account\s+include\s+common-account/=" "$pam_su_config") - elif [ -e /etc/arch-release ]; then - # Get location of system-remote-login. - insert=$($sed -rn "/^auth\s+include\s+system-remote-login/=" "$pam_sshd_config") - # TODO: find su_insert point for arch linux. - elif is_freebsd; then - # Get location of the first auth occurrence - insert=$($sed -rn '/^auth/=' "$pam_sshd_config" | head -1) - fi - - added_config="$added_comment" - if ! grep -qE '^auth.*pam_group' "$pam_sshd_config"; then - added_config="${added_config}\n${pam_auth_group}" - fi - - # This auth entry for OS Login+two factor MUST be added last, as it will - # short-circuit processing of the auth stack via [success=ok]. auth stack - # entries after this one will not be processed. - if [ -n "$two_factor" ] && ! grep -qE '^auth.*oslogin' "$pam_sshd_config"; then - added_config="${added_config}\n${pam_auth_oslogin}" - fi - - # Insert auth modules at top of `sshd:auth` stack. - if [ -n "$insert" ] && [ "$added_config" != "$added_comment" ]; then - $sed -i"" "${insert}i ${added_config}" "$pam_sshd_config" - fi - - # Insert su blocker at top of `su:account` stack. - if [ -n "$su_insert" ] && ! grep -qE "$pam_account_su" "$pam_su_config"; then - added_su_config="${added_comment}\n${pam_account_su}" - $sed -i"" "${su_insert}i ${added_su_config}" "$pam_su_config" - fi - - # Append account modules at end of `sshd:account` stack. - if ! grep -qE '^account.*oslogin' "$pam_sshd_config"; then - added_config="\\\n${added_comment}\n${pam_account_admin}\n${pam_account_oslogin}" - account_end=$($sed -n '/^account/=' "$pam_sshd_config" | tail -1) - $sed -i"" "${account_end}a ${added_config}" "$pam_sshd_config" - fi - - # Append mkhomedir module at end of `sshd:session` stack. - if ! grep -qE '^session.*mkhomedir' "$pam_sshd_config"; then - added_config="\\\n${added_comment}\n${pam_session_homedir}" - session_end=$($sed -n '/^session/=' "$pam_sshd_config" | tail -1) - $sed -i"" "${session_end}a ${added_config}" "$pam_sshd_config" - fi -) - -restore_pam_config() { - local pam_sshd_config="${1:-${pam_sshd_config}}" - local pam_su_config="${1:-${pam_su_config}}" - - $sed -i"" "/${added_comment}/d" "$pam_sshd_config" - $sed -i"" "/pam_oslogin/d" "$pam_sshd_config" - $sed -i"" "/^session.*mkhomedir/d" "$pam_sshd_config" - $sed -i"" "/^auth.*pam_group/d" "$pam_sshd_config" - - $sed -i"" "/${added_comment}/d" "$pam_su_config" - $sed -i"" "/pam_oslogin/d" "$pam_su_config" -} - -modify_group_conf() { - # In FreeBSD there is no pam_group config file similar to - # /etc/security/group.conf. - if is_freebsd; then - return - fi - - local group_config="${1:-${group_config}}" - local group_conf_entry="sshd;*;*;Al0000-2400;adm,dip,docker,lxd,plugdev,video" - - if ! grep -q "$group_conf_entry" "$group_config"; then - $sed -i"" "\$a ${added_comment}\n${group_conf_entry}" "$group_config" - fi -} - -restore_group_conf() { - # In FreeBSD there is no pam_group config file similar to - # /etc/security/group.conf. - if is_freebsd; then - return - fi - - local group_config="${1:-${group_config}}" - - $sed -i"" "/${added_comment}/{n;d}" "$group_config" - $sed -i"" "/${added_comment}/d" "$group_config" -} - -restart_service() { - local service="$1" - - # The other options will be wrappers to systemctl on - # systemd-enabled systems, so stop if found. - if readlink -f /sbin/init|grep -q systemd; then - if systemctl is-active --quiet "$service"; then - systemctl restart "$service" - return $? - else - return 0 - fi - fi - - # Use the service helper if it exists. - if command -v service > /dev/null; then - if ! service "$service" status 2>&1 | grep -Eq "unrecognized|does not exist"; then - service "$service" restart - return $? - else - return 0 - fi - fi - - # Fallback to trying sysvinit script of the same name. - if command -v /etc/init.d/"$service" > /dev/null; then - if /etc/init.d/"$service" status > /dev/null 2>&1; then - /etc/init.d/"$service" restart - return $? - else - return 0 - fi - fi - - # We didn't find any way to restart this service. - return 1 -} - -# Restart sshd unless --norestartsshd flag is set. -restart_sshd() { - if [ -n "$no_restart_sshd" ]; then - return 0 - fi - echo "Restarting SSHD" - for svc in "ssh" "sshd"; do - restart_service "$svc" - done -} - -restart_svcs() { - echo "Restarting optional services." - for svc in "nscd" "unscd" "systemd-logind" "cron" "crond"; do - restart_service "$svc" - done -} - -setup_google_dirs() { - for dir in "$sudoers_dir" "$users_dir"; do - [ -d "$dir" ] && continue - mkdir -p "$dir" - chmod 750 "$dir" - if fixfiles=$(command -v fixfiles); then - $fixfiles restore "$dir" - fi - done - echo "#includedir ${sudoers_dir}" > "$sudoers_file" - chmod 0440 "$sudoers_file" -} - -remove_google_dirs() { - for dir in "$sudoers_dir" "$users_dir"; do - rm -rf "$dir" - done - rm -f "$sudoers_file" -} - -activate() { - for func in modify_sshd_conf modify_nsswitch_conf \ - modify_pam_config setup_google_dirs restart_svcs restart_sshd \ - modify_group_conf; do - $func - [ $? -eq 0 ] || return 1 - done -} - -deactivate() { - for func in remove_google_dirs restore_nsswitch_conf \ - restore_sshd_conf restore_pam_config restart_svcs restart_sshd \ - restore_group_conf; do - $func - done -} - -# get_status checks each file for appropriate updates and exits on first -# failure. Checks for two factor config changes only if requested. -get_status() ( - set -e - - grep -Eq '^account.*oslogin' "$pam_sshd_config" - grep -Eq 'google_authorized_keys' "$sshd_config" - grep -Eq 'passwd:.*oslogin' "$nss_config" - if [ -n "$two_factor" ]; then - grep -Eq '^auth.*oslogin' "$pam_sshd_config" - grep -Eq '^(AuthenticationMethods|RequiredAuthentications2).*publickey,keyboard-interactive' "$sshd_config" - fi -) - -usage() { - echo "Usage: $(basename "$0") {activate|deactivate|status} [--norestartsshd] [--twofactor]" - echo "This script will activate or deactivate the features for" - echo "Google Compute Engine OS Login and (optionally) two-factor authentication." - echo "This script must be run as root." - exit 1 -} - - -# Main -if [ $(id -u) -ne 0 ] || [ $# -lt 1 ]; then - usage -fi - -sed="sed" -is_freebsd && sed="gsed" - -while [ $# -gt 0 ]; do - case "$1" in - --norestartsshd) - no_restart_sshd="true" - shift - ;; - --twofactor) - two_factor="true" - shift - ;; - activate) - action="activate" - shift - ;; - deactivate) - action="deactivate" - shift - ;; - status) - action="status" - shift - ;; - *) - shift - ;; - esac -done - -case "$action" in - activate) - echo "Activating Google Compute Engine OS Login." - activate - if [ $? -ne 0 ]; then - echo "Failed to apply changes, rolling back" - deactivate - exit 1 - fi - ;; - deactivate) - echo "Deactivating Google Compute Engine OS Login." - deactivate - ;; - status) - get_status - exit $? - ;; - *) - usage - ;; -esac diff --git a/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8 b/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8 deleted file mode 100644 index aaf4f8e..0000000 --- a/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8 +++ /dev/null @@ -1,48 +0,0 @@ -'\" t -.TH "NSS\-CACHE\-OSLOGIN" "8" "2019-06-06" "Google Cloud" - -.\" IF GNU troff set Aq to sequence aq (Apostrophe quote) -.ie \n(.g .ds Aq \(aq -.\" ELSE set Aq to ' -.el .ds Aq ' - -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l - -.SH "NAME" -nss-cache-oslogin, libnss_cache_oslogin.so.2 \- UNIX implementation for OS Login Users and Groups with local caching\&. - -.SH "SYNOPSIS" -libnss_cache_oslogin\&.so\&.2 - -.SH "DESCRIPTION" -\fBnss\-cache\-oslogin\fR is a plug\-in module for the GNU Name Service Switch -(NSS) functionality of the GNU C Library (\fBglibc\fR)\&. -This module provides UNIX name resolution from a local cache of users and groups -configured in the \fIGoogle Cloud OS Login\fR system\&. -The "passwd" and "group" services are supported by this module\&. -.PP -To use the NSS module, add "cache_oslogin" to the appropriate service lines -in nsswitch\&.conf\&. -It is recommended to place "cache_oslogin" after any system provided modules -and before the "oslogin" module, as it is a pass-through cache. - -.SH "FILES" -.IP /etc/oslogin_passwd.cache -user cache file -.IP /etc/oslogin_group.cache -group cache file - -.SH "NOTES" -Documentation for the Google Cloud OS Login service is available online at -.UR "https://cloud.google.com/compute/docs/oslogin" -.UE - -.SH "SEE ALSO" -.BR nss-oslogin (5), -.BR nsswitch.conf (5), -.BR nss (5), -.BR getent (1), -.BR initgroups (3) diff --git a/packages/google-compute-engine-oslogin/man/nss-oslogin.8 b/packages/google-compute-engine-oslogin/man/nss-oslogin.8 deleted file mode 100644 index 3f4c763..0000000 --- a/packages/google-compute-engine-oslogin/man/nss-oslogin.8 +++ /dev/null @@ -1,41 +0,0 @@ -'\" t -.TH "NSS\-OSLOGIN" "8" "2019-06-06" "Google Cloud" - -.\" IF GNU troff set Aq to sequence aq (Apostrophe quote) -.ie \n(.g .ds Aq \(aq -.\" ELSE set Aq to ' -.el .ds Aq ' - -.\" disable hyphenation -.nh -.\" disable justification (adjust text to left margin only) -.ad l - -.SH "NAME" -nss-oslogin, libnss_oslogin.so.2 \- UNIX implementation for OS Login Users and Groups\&. - -.SH "SYNOPSIS" -libnss_oslogin\&.so\&.2 - -.SH "DESCRIPTION" -\fBnss\-oslogin\fR is a plug\-in module for the GNU Name Service Switch (NSS) -functionality of the GNU C Library (\fBglibc\fR). -This module provides UNIX name resolution for users and groups configured -through the \fIGoogle Cloud OS Login\fR system\&. -The "passwd", "group", and "initgroups" services are supported by this module. -.PP -To use the NSS module, add "oslogin" to the appropriate service lines -in nsswitch\&.conf\&. -It is recommended to place "oslogin" as the last entry for each service. - -.SH "NOTES" -Documentation for the Google Cloud OS Login service is available online at -.UR "https://cloud.google.com/compute/docs/oslogin" -.UE - -.SH "SEE ALSO" -.BR nss-cache-oslogin (8), -.BR nsswitch.conf (5), -.BR nss (5), -.BR getent (1), -.BR initgroups (3) diff --git a/packages/google-compute-engine-oslogin/packaging/debian/changelog b/packages/google-compute-engine-oslogin/packaging/debian/changelog deleted file mode 100644 index 5eb8a46..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/changelog +++ /dev/null @@ -1,164 +0,0 @@ -google-compute-engine-oslogin (1:20190801.00-g1) stable; urgency=medium - - * Correct JSON refcount decrementing. - - -- Google Cloud Team Thu, 01 Aug 2019 13:57:16 -0700 - -google-compute-engine-oslogin (1:20190729.00-g1) stable; urgency=medium - - * Remove unnecessary binary search logic. - - -- Google Cloud Team Mon, 29 Jul 2019 10:11:00 -0700 - -google-compute-engine-oslogin (1:20190708.00-g1) stable; urgency=medium - - * Restructure Makefile and Debian control files. - * Add man pages. - - -- Google Cloud Team Mon, 08 Jul 2019 10:20:01 -0700 - -google-compute-engine-oslogin (1.5.3-1) unstable; urgency=low - - * Update OS Login control file for FreeBSD support. - - -- Google Cloud Team Wed, 22 May 2019 12:00:00 -0700 - -google-compute-engine-oslogin (1.5.2-1) unstable; urgency=low - - * Fix pam_group ordering detection. - * Restart cron on OS Login control. - * Add PAM entry to su:account stack. - - -- Google Cloud Team Tue, 16 Apr 2019 12:00:00 -0700 - -google-compute-engine-oslogin (1.5.1-1) unstable; urgency=low - - * Fix two factor auth action name. - - -- Google Cloud Team Tue, 13 Mar 2019 12:00:00 -0700 - -google-compute-engine-oslogin (1.5.0-1) unstable; urgency=low - - * Support Google prompt for two factor authentication. - - -- Google Cloud Team Tue, 19 Feb 2019 12:00:00 -0700 - -google-compute-engine-oslogin (1.4.3-1) unstable; urgency=low - - * Improve OS Login control file for BSD support. - * Improve SELinux support. - - -- Google Cloud Team Wed, 05 Dec 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.4.2-1+deb9) unstable; urgency=low - - * Improve OS Login control file. - * Restart systemd-logind on OS Login enable. - - -- Google Cloud Team Tue, 04 Dec 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.4.1-1+deb9) unstable; urgency=low - - * Improve SELinux support. - * Improve OS Login control file. - - -- Google Cloud Team Fri, 30 Nov 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.4.0-1+deb9) unstable; urgency=low - - * Support OS Login two factor authentication. - - -- Google Cloud Team Wed, 28 Nov 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.3.1-1+deb9) unstable; urgency=low - - * Add user name validation to pam modules. - * Return false on failed final load. - - -- Google Cloud Team Wed, 05 Sep 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.3.0-1+deb9) unstable; urgency=low - - * Include libnss cache as part of the OS Login package. - - -- Google Cloud Team Tue, 01 May 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.2.0-1+deb9) unstable; urgency=low - - * Add support for NSS cache. - - -- Google Cloud Team Thu, 08 Mar 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.5-1+deb9) unstable; urgency=low - - * Clear the CURL_GLOBAL_SSL bit on curl initialization. - - -- Google Cloud Team Mon, 26 Feb 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.4-1+deb9) unstable; urgency=low - - * Close socket connections when requesting metadata. - - -- Google Cloud Team Mon, 29 Jan 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.3-1+deb9) unstable; urgency=low - - * Change the OS Login uid restriction to allow uid 1000. - - -- Google Cloud Team Thu, 25 Jan 2018 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.2-1+deb9) unstable; urgency=low - - * Fix parsing logic for expiration time on SSH public keys. - * Fix home directory creation PAM config. - - -- MAINTAINER Wed, 29 Nov 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.1-1+deb9) unstable; urgency=low - - * Remove logging when checking OS Login status. - - -- MAINTAINER Wed, 25 Oct 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.1.0-1+deb9) unstable; urgency=low - - * OS Login is enabled via the google-compute-engine package. - - -- MAINTAINER Tue, 17 Oct 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.5-1+deb9) unstable; urgency=low - - * JSON parser accepts string types for int64 values. - - -- MAINTAINER Fri, 06 Oct 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.4-1+deb9) unstable; urgency=low - - * JSON parser casts uid and gid to unsigned integers. - - -- MAINTAINER Tue, 20 Sep 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.3-1+deb9) unstable; urgency=low - - * Strictly check for HTTP code 200. - - -- MAINTAINER Tue, 25 Aug 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.2-1+deb9) unstable; urgency=low - - * Improve security in case of transient errors. - - -- MAINTAINER Tue, 15 Aug 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.1-1+deb9) unstable; urgency=low - - * Fix for restarting sshd and nscd. - - -- MAINTAINER Mon, 17 Jul 2017 12:00:00 -0700 - -google-compute-engine-oslogin (1.0.0-1+deb9) unstable; urgency=low - - * Team Upload. - * Initial release. - - -- MAINTAINER Thu, 22 Jun 2017 12:00:00 -0700 diff --git a/packages/google-compute-engine-oslogin/packaging/debian/compat b/packages/google-compute-engine-oslogin/packaging/debian/compat deleted file mode 100644 index ec63514..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/packages/google-compute-engine-oslogin/packaging/debian/control b/packages/google-compute-engine-oslogin/packaging/debian/control deleted file mode 100644 index ac14124..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/control +++ /dev/null @@ -1,13 +0,0 @@ -Source: google-compute-engine-oslogin -Maintainer: Google Cloud Team -Section: misc -Priority: optional -Standards-Version: 3.9.8 -Build-Depends: debhelper (>= 9), libcurl4-openssl-dev, libjson-c-dev | libjson0-dev, libpam-dev - -Package: google-compute-engine-oslogin -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Google Compute Engine OS Login - Contains libraries, applications and configurations for using OS Login - on Google Compute Engine Virtual Machine Instances. diff --git a/packages/google-compute-engine-oslogin/packaging/debian/copyright b/packages/google-compute-engine-oslogin/packaging/debian/copyright deleted file mode 100644 index f1c5775..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/copyright +++ /dev/null @@ -1,27 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: google-compute-engine-oslogin -Upstream-Contact: gc-team@google.com - -Files: * -Copyright: Copyright 2017 Google Inc. -License: Apache-2.0 - -Files: debian/* -Copyright: Copyright 2017 Google Inc. -License: Apache-2.0 - -License: Apache-2.0 - 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. - . - On Debian systems, the complete text of the Apache version 2.0 license - can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/packages/google-compute-engine-oslogin/packaging/debian/rules b/packages/google-compute-engine-oslogin/packaging/debian/rules deleted file mode 100755 index 8ae94b8..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/rules +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/make -f -%: - dh $@ - -override_dh_auto_install: - dh_auto_install -- LIBDIR=/lib/$(DEB_HOST_MULTIARCH) diff --git a/packages/google-compute-engine-oslogin/packaging/debian/source/format b/packages/google-compute-engine-oslogin/packaging/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/packages/google-compute-engine-oslogin/packaging/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) 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 deleted file mode 100644 index d9b67bd..0000000 --- a/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec +++ /dev/null @@ -1,101 +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. - -# For EL7, if building on CentOS, override dist to be el7. -%if 0%{?rhel} == 7 - %define dist .el7 -%endif - -Name: google-compute-engine-oslogin -Epoch: 1 -Version: %{_version} -Release: g1%{?dist} -Summary: OS Login Functionality for Google Compute Engine - -License: ASL 2.0 -Source0: %{name}_%{version}.orig.tar.gz - -BuildRequires: boost-devel -BuildRequires: gcc-c++ -BuildRequires: make -BuildRequires: libcurl -BuildRequires: json-c-devel -BuildRequires: pam-devel -%if 0%{?rhel} == 8 -BuildRequires: python3-policycoreutils -Requires: python3-policycoreutils -%else -BuildRequires: policycoreutils-python -Requires: policycoreutils-python -%endif -Requires: boost-regex -Requires: json-c - -%description -This package contains several libraries and changes to enable OS Login functionality -for Google Compute Engine. - -%global debug_package %{nil} - -%prep -%setup - -%build -make %{?_smp_mflags} LDLIBS="-lcurl -ljson-c -lboost_regex" - -%install -rm -rf %{buildroot} -make install DESTDIR=%{buildroot} LIBDIR=/%{_lib} INSTALL_SELINUX=y - -%files -%doc -/%{_lib}/libnss_oslogin-%{version}.so -/%{_lib}/libnss_cache_oslogin-%{version}.so -/%{_lib}/libnss_oslogin.so.2 -/%{_lib}/libnss_cache_oslogin.so.2 -/%{_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 -if [ $1 -gt 1 ]; then # This is an upgrade. - if semodule -l | grep -qi oslogin.el6; then - echo "Removing old SELinux module for OS Login." - semodule -r oslogin.el6 - fi -fi -echo "Installing SELinux module for OS Login." -semodule -i /usr/share/selinux/packages/oslogin.pp -if [ -e /var/google-sudoers.d ]; then - fixfiles restore /var/google-sudoers.d -fi - -%postun -/sbin/ldconfig -if [ $1 = 0 ]; then # This is an uninstall. - if semodule -l|grep -qi oslogin; then - echo "Removing SELinux module for OS Login." - semodule -r oslogin - fi -fi - -%changelog diff --git a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh b/packages/google-compute-engine-oslogin/packaging/setup_deb.sh deleted file mode 100755 index 5b3f893..0000000 --- a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# 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. - -NAME="google-compute-engine-oslogin" -VERSION="20190801.00" - -DEB=$(cut -d. -f1 /dev/null - -rm -rf /tmp/debpackage -mkdir /tmp/debpackage -tar czvf /tmp/debpackage/${NAME}_${VERSION}.orig.tar.gz --exclude .git \ - --exclude packaging --transform "s/^\./${NAME}-${VERSION}/" . - -pushd /tmp/debpackage -tar xzvf ${NAME}_${VERSION}.orig.tar.gz - -cd ${NAME}-${VERSION} - -cp -r ${working_dir}/packaging/debian ./ -echo "Building on Debian ${DEB}, modifying latest changelog entry." -sed -r -i"" "1s/^${NAME} \((.*)\) (.+;.*)/${NAME} (\1+deb${DEB}) \2/" \ - debian/changelog - -echo "Starting build" -DEB_BUILD_OPTIONS=noddebs debuild -us -uc - -popd diff --git a/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh b/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh deleted file mode 100755 index d0bef7b..0000000 --- a/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# 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. - - -NAME="google-compute-engine-oslogin" -VERSION="20190801.00" - -rpm_working_dir=/tmp/rpmpackage/${NAME}-${VERSION} -working_dir=${PWD} -if [[ $(basename "$working_dir") != $NAME ]]; then - echo "Packaging scripts must be run from top of package dir." - exit 1 -fi - -sudo yum -y install rpmdevtools make gcc-c++ json-c \ - libcurl-devel pam-devel boost-devel json-c-devel - -if grep -q '^\(CentOS\|Red Hat\)[^0-9]*8\..' /etc/redhat-release; then - sudo yum -y install python3-policycoreutils -else - sudo yum -y install policycoreutils-python -fi - -rm -rf /tmp/rpmpackage -mkdir -p ${rpm_working_dir}/{SOURCES,SPECS} -cp packaging/${NAME}.spec ${rpm_working_dir}/SPECS/ - -tar czvf ${rpm_working_dir}/SOURCES/${NAME}_${VERSION}.orig.tar.gz --exclude .git --exclude packaging --transform "s/^\./${NAME}-${VERSION}/" . - -rpmbuild --define "_topdir ${rpm_working_dir}/" --define "_version ${VERSION}" \ - -ba ${rpm_working_dir}/SPECS/${NAME}.spec diff --git a/packages/google-compute-engine-oslogin/selinux/Makefile b/packages/google-compute-engine-oslogin/selinux/Makefile deleted file mode 100644 index c858c9d..0000000 --- a/packages/google-compute-engine-oslogin/selinux/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SELINUX POLICY -MOD_BASE = oslogin -SELINUX_MODULE_SRC = $(MOD_BASE).te -SELINUX_MOD_FILE = $(MOD_BASE).mod -SELINUX_FC_FILE = $(MOD_BASE).fc -SELINUX_MODULE = $(MOD_BASE).pp - -all: $(SELINUX_MODULE) - -$(SELINUX_MOD_FILE): $(SELINUX_MODULE_SRC) - checkmodule -M -m -o $(SELINUX_MOD_FILE) $(SELINUX_MODULE_SRC) - -$(SELINUX_MODULE): $(SELINUX_MOD_FILE) - semodule_package -o $(SELINUX_MODULE) -m $(SELINUX_MOD_FILE) -f $(SELINUX_FC_FILE) - -clean: - rm -f $(SELINUX_MODULE) $(SELINUX_MOD_FILE) diff --git a/packages/google-compute-engine-oslogin/selinux/README.md b/packages/google-compute-engine-oslogin/selinux/README.md deleted file mode 100644 index b2cc5a9..0000000 --- a/packages/google-compute-engine-oslogin/selinux/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## SELinux policy module for OS Login - -This module adds specific policy updates which enable OS Login features to -function on SELinux-enabled systems (currently default on GCE RHEL6/7 images). - -It primarily enables `SSHD(8)` to make network calls to the metadata server to -verify OS Login users, and to create per-user `SUDOERS(5)` files in -`/var/google-sudoers.d` - -### Building the module - -The provided Makefile compiles type enforcement and file context files into a -binary SELinux policy module. It must be compiled on the oldest version of the -destination OS you intend to support, as binary module versions are not -backwards compatible. Therefore, this Makefile is not run as part of the normal -packaging process but is done 'by hand', only when changes are made to the -policy. diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.fc b/packages/google-compute-engine-oslogin/selinux/oslogin.fc deleted file mode 100644 index 3e70358..0000000 --- a/packages/google-compute-engine-oslogin/selinux/oslogin.fc +++ /dev/null @@ -1,2 +0,0 @@ -/var/google-sudoers.d(/.*)? system_u:object_r:google_t:s0 -/var/google-users.d(/.*)? system_u:object_r:google_t:s0 diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.pp b/packages/google-compute-engine-oslogin/selinux/oslogin.pp deleted file mode 100644 index 6ec6ed0..0000000 Binary files a/packages/google-compute-engine-oslogin/selinux/oslogin.pp and /dev/null differ diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.te b/packages/google-compute-engine-oslogin/selinux/oslogin.te deleted file mode 100644 index 381f769..0000000 --- a/packages/google-compute-engine-oslogin/selinux/oslogin.te +++ /dev/null @@ -1,24 +0,0 @@ - -module oslogin 1.0; - - -require { - attribute file_type; - attribute non_security_file_type; - type http_port_t; - type sshd_t; - class tcp_socket name_connect; - class file { create getattr setattr write open unlink }; - class dir { search write remove_name add_name }; -} - -#============= types ============== - -type google_t; # defined in oslogin.fc -typeattribute google_t file_type, non_security_file_type; - -#============= sshd_t ============== - -allow sshd_t google_t:file { create getattr setattr write open unlink }; -allow sshd_t google_t:dir { search write remove_name add_name }; -allow sshd_t http_port_t:tcp_socket name_connect; 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 -#include -#include - -#include - -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 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 -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - - -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 - -#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 - -#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 -#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/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 -#include -#include -#include - -#include -#include - -#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 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 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* users, - int* errnop); - -// Iterates through all groups for a user, storing results in a provided string -// vector. -bool GetGroupsForUser(string username, std::vector* groups, int* errnop); - -// Parses a JSON groups response, storing results in a provided Group vector. -bool ParseJsonToGroups(const string& json, std::vector* groups); - -// Parses a JSON users response, storing results in a provided string vector. -bool ParseJsonToUsers(const string& json, std::vector* 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 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* 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 - */ - -#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/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 -#include - -#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; -} - -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -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 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 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -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 challenges; - if (!ParseJsonToChallenges(response, &challenges)) { - PAM_SYSLOG(pamh, LOG_ERR, - "Failed to parse challenge values from JSON response"); - return PAM_PERM_DENIED; - } - - std::map 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::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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if defined(__clang__) || __GNUC__ > 4 || \ - (__GNUC__ == 4 && \ - (__GNUC_MINOR__ > 9 || (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 0))) -#include -#define Regex std -#else -#include -#define Regex boost -#endif - -#include -#include - -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(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(userp); - std::streamsize len = size * nmemb; - if (os.write(static_cast(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* 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* 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 ParseJsonToSshKeys(const string& json) { - std::vector 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 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* 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 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* 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* 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 diff --git a/packages/google-compute-engine-oslogin/test/Makefile b/packages/google-compute-engine-oslogin/test/Makefile deleted file mode 100644 index 83d23fd..0000000 --- a/packages/google-compute-engine-oslogin/test/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -TOPDIR = $(realpath ..) - -CPPFLAGS += -I$(TOPDIR)/src/include -I/usr/include/json-c -CXXFLAGS += -g -Wall -Wextra -std=c++11 -LDLIBS = -lcurl -ljson-c -lpthread - -all : test_runner non_network_tests - -clean : - rm -f test_runner *.o - -gtest-all.o : $(GTEST_DIR)/src/gtest-all.cc - $(CXX) $(CXXFLAGS) -isystem $(GTEST)/include -I$(GTEST) $(CPPFLAGS) -c $^ - -test_runner : oslogin_utils_test.o $(TOPDIR)/src/utils.o gtest-all.o - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) - -non_network_tests : test_runner - ./test_runner --gtest_filter=*-FindGroupTest.*:GetUsersForGroupTest.* - -network_tests : test_runner ping reset - ./test_runner --gtest_filter=FindGroupTest.*:GetUsersForGroupTest.* - -# run as $ make tests GTESTARGS="--gtest_filter=FindGroupTest.*" -tests : test_runner - ./test_runner ${GTESTARGS} - -ping : - nc -vzw2 metadata.google.internal 80 >/dev/null 2>&1 - -reset : - curl -Ss http://metadata.google.internal/reset >/dev/null 2>&1 - -.PHONY : all clean tests ping reset gtest prowtest diff --git a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc b/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc deleted file mode 100644 index 6c9c1df..0000000 --- a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc +++ /dev/null @@ -1,627 +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 libgtest-dev and gtest compiled and installed. -#include -#include -#include -#include -#include - -using std::string; -using std::vector; - -namespace oslogin_utils { - -// Test that the buffer can successfully append multiple strings. -TEST(BufferManagerTest, TestAppendString) { - size_t buflen = 20; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - - char* first_string; - char* second_string; - int test_errno = 0; - oslogin_utils::BufferManager buffer_manager(buffer, buflen); - buffer_manager.AppendString("test1", &first_string, &test_errno); - buffer_manager.AppendString("test2", &second_string, &test_errno); - ASSERT_EQ(test_errno, 0); - ASSERT_STREQ(first_string, "test1"); - ASSERT_STREQ(second_string, "test2"); - ASSERT_STREQ(buffer, "test1"); - ASSERT_STREQ((buffer + 6), "test2"); -} - -// Test that attempting to append a string larger than the buffer can handle -// fails with ERANGE. -TEST(BufferManagerTest, TestAppendStringTooLarge) { - size_t buflen = 1; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - - char* first_string; - int test_errno = 0; - oslogin_utils::BufferManager buffer_manager(buffer, buflen); - ASSERT_FALSE( - buffer_manager.AppendString("test1", &first_string, &test_errno)); - ASSERT_EQ(test_errno, ERANGE); -} - -// Test successfully loading and retrieving an array of JSON posix accounts. -TEST(NssCacheTest, TestLoadJsonArray) { - NssCache nss_cache(2); - string test_user1 = - "{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337," - "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}"; - string test_user2 = - "{\"name\":\"bar@example.com\"," - "\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"bar\",\"uid\":1338,\"gid\":1338," - "\"homeDirectory\":\"/home/bar\",\"shell\":\"/bin/bash\"}]}"; - string response = "{\"loginProfiles\": [" + test_user1 + ", " + test_user2 + - "], \"nextPageToken\": \"token\"}"; - - ASSERT_TRUE(nss_cache.LoadJsonArrayToCache(response)); - - size_t buflen = 500; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - - // Verify that the first user was stored. - ASSERT_TRUE(nss_cache.HasNextPasswd()); - ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, 0); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1337); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); - - // Verify that the second user was stored. - ASSERT_TRUE(nss_cache.HasNextPasswd()); - ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, 0); - ASSERT_EQ(result.pw_uid, 1338); - ASSERT_EQ(result.pw_gid, 1338); - ASSERT_STREQ(result.pw_name, "bar"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/bar"); - - // Verify that there are no more users stored. - ASSERT_FALSE(nss_cache.HasNextPasswd()); - ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, ENOENT); -} - -// Test successfully loading and retrieving a partial array. -TEST(NssCacheTest, TestLoadJsonPartialArray) { - NssCache nss_cache(2); - string test_user1 = - "{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337," - "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}"; - string response = - "{\"loginProfiles\": [" + test_user1 + "], \"nextPageToken\": \"token\"}"; - - ASSERT_TRUE(nss_cache.LoadJsonArrayToCache(response)); - - size_t buflen = 500; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - - // Verify that the first user was stored. - ASSERT_TRUE(nss_cache.HasNextPasswd()); - ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, 0); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1337); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); - - ASSERT_EQ(nss_cache.GetPageToken(), "token"); - - // Verify that there are no more users stored. - ASSERT_FALSE(nss_cache.HasNextPasswd()); - ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, ENOENT); -} - -// Test successfully loading and retrieving the final response. -TEST(NssCacheTest, TestLoadJsonFinalResponse) { - NssCache nss_cache(2); - string response = "{\"nextPageToken\": \"0\"}"; - - ASSERT_FALSE(nss_cache.LoadJsonArrayToCache(response)); - ASSERT_EQ(nss_cache.GetPageToken(), ""); - - size_t buflen = 500; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - - // Verify that there are no more users stored. - ASSERT_FALSE(nss_cache.HasNextPasswd()); - ASSERT_TRUE(nss_cache.OnLastPage()); - ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno)); - ASSERT_EQ(test_errno, ENOENT); -} - -// Tests that resetting, and checking HasNextPasswd does not crash. -TEST(NssCacheTest, ResetNullPtrTest) { - NssCache nss_cache(2); - nss_cache.Reset(); - ASSERT_FALSE(nss_cache.HasNextPasswd()); -} - -// Test parsing a valid JSON response from the metadata server. -TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceeds) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1338," - "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1338); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); -} - -// Test parsing a valid JSON response from the metadata server with uid > 2^31. -TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithHighUid) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":4294967295,\"gid\":" - "4294967295,\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(result.pw_uid, 4294967295); - ASSERT_EQ(result.pw_gid, 4294967295); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); -} - -TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithStringUid) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":\"1337\",\"gid\":" - "\"1338\",\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1338); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); -} - -TEST(ParseJsonPasswdTest, ParseJsonToPasswdNoLoginProfilesSucceeds) { - string test_user = - "{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337," - "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1337); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); -} - -// Test parsing a JSON response without enough space in the buffer. -TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithERANGE) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337," - "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}"; - - size_t buflen = 1; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(test_errno, ERANGE); -} - -// Test parsing malformed JSON responses. -TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithEINVAL) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\": \"bad_stuff\"" - ",\"gid\":1337,\"homeDirectory\":\"/home/foo\"," - "\"shell\":\"/bin/bash\"}]}]}"; - string test_user2 = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\": 1337," - "\"gid\":\"bad_stuff\",\"homeDirectory\":\"/home/foo\"," - "\"shell\":\"/bin/bash\"}]}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(test_errno, EINVAL); - // Reset errno. - test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user2, &result, &buf, &test_errno)); - ASSERT_EQ(test_errno, 0); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1337); -} - -// Test parsing a partially filled response. Validate should fill empty fields -// with default values. -TEST(ParseJsonPasswdTest, ValidatePartialJsonResponse) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337}]" - "}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(result.pw_uid, 1337); - ASSERT_EQ(result.pw_gid, 1337); - ASSERT_STREQ(result.pw_name, "foo"); - ASSERT_STREQ(result.pw_shell, "/bin/bash"); - ASSERT_STREQ(result.pw_dir, "/home/foo"); -} - -// Test parsing an invalid response. Validate should cause the parse to fail if -// there is no uid. -TEST(ParseJsonPasswdTest, ValidateInvalidJsonResponse) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"gid\":1337}]" - "}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - struct passwd result; - int test_errno = 0; - ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno)); - ASSERT_EQ(test_errno, EINVAL); -} - -// Test parsing a valid JSON response from the metadata server. -TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceeds) { - string test_group = "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":123452}]}"; - - std::vector groups; - ASSERT_TRUE(ParseJsonToGroups(test_group, &groups)); - ASSERT_EQ(groups[0].gid, 123452); - ASSERT_EQ(groups[0].name, "demo"); -} - -// Test parsing a valid JSON response from the metadata server with gid > 2^31. -TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithHighGid) { - string test_group = - "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":4294967295}]}"; - - std::vector groups; - ASSERT_TRUE(ParseJsonToGroups(test_group, &groups)); - ASSERT_EQ(groups[0].gid, 4294967295); - ASSERT_EQ(groups[0].name, "demo"); -} - -TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithStringGid) { - string test_group = - "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"123452\"}]}"; - - std::vector groups; - ASSERT_TRUE(ParseJsonToGroups(test_group, &groups)); - ASSERT_EQ(groups[0].gid, 123452); - ASSERT_EQ(groups[0].name, "demo"); -} - -// Test parsing malformed JSON responses. -TEST(ParseJsonToGroupsTest, ParseJsonToGroupsFails) { - string test_badgid = - "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"this-should-be-int\"}]}"; - string test_nogid = "{\"posixGroups\":[{\"name\":\"demo\"}]}"; - string test_noname = "{\"posixGroups\":[{\"gid\":123452}]}"; - - std::vector groups; - ASSERT_FALSE(ParseJsonToGroups(test_badgid, &groups)); - ASSERT_FALSE(ParseJsonToGroups(test_nogid, &groups)); - ASSERT_FALSE(ParseJsonToGroups(test_noname, &groups)); -} - -// Test parsing a valid JSON response from the metadata server. -TEST(ParseJsonToUsersTest, ParseJsonToUsersSucceeds) { - string test_group_users = - "{\"usernames\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\"," - "\"user0005\"]}"; - - std::vector users; - ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users)); - ASSERT_FALSE(users.empty()); - ASSERT_EQ(users.size(), 5); - - ASSERT_EQ(users[0], "user0001"); - ASSERT_EQ(users[1], "user0002"); - ASSERT_EQ(users[2], "user0003"); - ASSERT_EQ(users[3], "user0004"); - ASSERT_EQ(users[4], "user0005"); -} - -// Test parsing a valid JSON response from the metadata server. -TEST(ParseJsonToUsersTest, ParseJsonToUsersEmptyGroupSucceeds) { - string test_group_users = "{\"usernames\":[]}"; - - std::vector users; - ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users)); - ASSERT_TRUE(users.empty()); -} - -// Test parsing malformed JSON responses. -TEST(ParseJsonToUsersTest, ParseJsonToUsersFails) { - string test_group_users = - "{\"badstuff\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\"," - "\"user0005\"]}"; - - std::vector users; - ASSERT_FALSE(ParseJsonToUsers(test_group_users, &users)); -} - -TEST(GetUsersForGroupTest, GetUsersForGroupSucceeds) { - string response; - long http_code; - ASSERT_TRUE( - HttpGet("http://metadata.google.internal/reset", &response, &http_code)); - - std::vector users; - int errnop = 0; - - ASSERT_TRUE(GetUsersForGroup("demo", &users, &errnop)); - ASSERT_FALSE(users.empty()); - ASSERT_EQ(users[0], "user000173_grande_focustest_org"); - ASSERT_EQ(errnop, 0); -} - -TEST(FindGroupTest, FindGroupByGidSucceeds) { - string response; - long http_code; - ASSERT_TRUE( - HttpGet("http://metadata.google.internal/reset", &response, &http_code)); - - size_t buflen = 200 * sizeof(char); - char* buffer = (char*)malloc(buflen); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - int errnop = 0; - - struct group grp = {}; - grp.gr_gid = 123452; - ASSERT_TRUE(FindGroup(&grp, &buf, &errnop)); - ASSERT_EQ(errnop, 0); -} - -TEST(FindGroupTest, FindGroupByNameSucceeds) { - string response; - long http_code; - ASSERT_TRUE( - HttpGet("http://metadata.google.internal/reset", &response, &http_code)); - - size_t buflen = 200 * sizeof(char); - char* buffer = (char*)malloc(buflen); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - int errnop; - - const char* match = "demo"; - struct group grp = {}; - grp.gr_name = (char*)match; - ASSERT_TRUE(FindGroup(&grp, &buf, &errnop)); -} - -TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" - "{\"primary\":true,\"username\":\"foo\",\"gid\":1337}]" - "}]}"; - - string email; - ASSERT_TRUE(ParseJsonToEmail(test_user, &email)); - ASSERT_EQ(email, "foo@example.com"); -} - -TEST(ParseJsonEmailTest, FailsParseEmail) { - string email; - ASSERT_FALSE(ParseJsonToEmail("random_junk", &email)); - ASSERT_EQ(email, ""); -} - -TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysSucceeds) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":" - "{\"fingerprint\": {\"key\": \"test_key\"}}}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - std::vector result = ParseJsonToSshKeys(test_user); - ASSERT_EQ(result.size(), 1); - ASSERT_EQ(result[0], "test_key"); -} - -TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysMultipleKeys) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":" - "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": " - "\"test_key2\"}}}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - std::vector result = ParseJsonToSshKeys(test_user); - ASSERT_EQ(result.size(), 2); - ASSERT_EQ(result[0], "test_key"); - ASSERT_EQ(result[1], "test_key2"); -} - -TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersExpiredKeys) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":" - "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": " - "\"test_key2\", \"expirationTimeUsec\": 0}}}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - std::vector result = ParseJsonToSshKeys(test_user); - ASSERT_EQ(result.size(), 1); - ASSERT_EQ(result[0], "test_key"); -} - -TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersMalformedExpiration) { - string test_user = - "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":" - "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": " - "\"test_key2\", \"expirationTimeUsec\": \"bad_stuff\"}}}]}"; - - size_t buflen = 200; - char* buffer = (char*)malloc(buflen * sizeof(char)); - ASSERT_STRNE(buffer, NULL); - BufferManager buf(buffer, buflen); - std::vector result = ParseJsonToSshKeys(test_user); - ASSERT_EQ(result.size(), 1); - ASSERT_EQ(result[0], "test_key"); -} - -TEST(ParseJsonAuthorizeSuccess, SuccessfullyAuthorized) { - string response = "{\"success\": true}"; - ASSERT_TRUE(ParseJsonToSuccess(response)); -} - -TEST(ValidateUserNameTest, ValidateValidUserNames) { - string cases[] = {"user", "_", ".", ".abc_", - "_abc-", "ABC", "A_.-", "ausernamethirtytwocharacterslong"}; - for (auto test_user : cases) { - ASSERT_TRUE(ValidateUserName(test_user)); - } -} - -TEST(ValidateUserNameTest, ValidateInvalidUserNames) { - string cases[] = { - "", - "!#$%^", - "-abc", - "#abc", - "^abc", - "abc*xyz", - "abc xyz", - "xyz*", - "xyz$", - "usernamethirtythreecharacterslong", - "../../etc/shadow", - }; - for (auto test_user : cases) { - ASSERT_FALSE(ValidateUserName(test_user)); - } -} - -TEST(ParseJsonKeyTest, TestKey) { - string test_json = "{\"some_key\":\"some_value\"}"; - string value; - ASSERT_TRUE(ParseJsonToKey(test_json, "some_key", &value)); - ASSERT_EQ(value, "some_value"); -} - -TEST(ParseJsonKeyTest, TestMissingKey) { - string test_json = "{\"some_key\":\"some_value\"}"; - string value; - ASSERT_FALSE(ParseJsonToKey(test_json, "some_other_key", &value)); - ASSERT_EQ(value, ""); -} - -TEST(ParseJsonChallengesTest, TestChallenges) { - string challenges_json = - "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":" - "\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":" - "\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":" - "\"AUTHZEN\",\"status\":\"PROPOSED\"}]}"; - vector challenges; - ASSERT_TRUE(ParseJsonToChallenges(challenges_json, &challenges)); - ASSERT_EQ(challenges.size(), 2); - ASSERT_EQ(challenges[0].id, 1); - ASSERT_EQ(challenges[0].type, "TOTP"); -} - -TEST(ParseJsonChallengesTest, TestMalformedChallenges) { - string challenges_json = - "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":" - "\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":" - "\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":" - "\"AUTHZEN\"}]}"; - vector challenges; - ASSERT_FALSE(ParseJsonToChallenges(challenges_json, &challenges)); - ASSERT_EQ(challenges.size(), 1); -} -} // namespace oslogin_utils -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} -- cgit v1.2.1