Merge ~kajiya/+git/google-compute-engine-oslogin:update-jammy-to-20240701.00 into ~ubuntu-core-dev/+git/google-compute-engine-oslogin:ubuntu/jammy

Proposed by Chloé Smith
Status: Merged
Merged at revision: 9f6f47c3cd1bab8dc2a8323e96928187405e435c
Proposed branch: ~kajiya/+git/google-compute-engine-oslogin:update-jammy-to-20240701.00
Merge into: ~ubuntu-core-dev/+git/google-compute-engine-oslogin:ubuntu/jammy
Diff against target: 779 lines (+313/-91)
12 files modified
OWNERS (+2/-2)
debian/changelog (+42/-0)
debian/links (+2/-2)
debian/patches/0002-inherit-cflags.patch (+23/-0)
debian/patches/series (+1/-0)
packaging/google-compute-engine-oslogin.spec (+1/-0)
src/Makefile (+49/-25)
src/include/oslogin_utils.h (+8/-0)
src/oslogin_utils.cc (+98/-62)
src/pam/pam_oslogin_admin.cc (+53/-0)
src/pam/pam_oslogin_login.cc (+27/-0)
test/oslogin_utils_test.cc (+7/-0)
Reviewer Review Type Date Requested Status
Utkarsh Gupta Approve
Review via email: mp+470198@code.launchpad.net

Commit message

* d/ch entry for jammy (LP: #2073166)
* Merge branch 'ubuntu-core-dev/ubuntu/master' into 'ubuntu-core-dev/ubuntu/jammy'

To post a comment you must log in.
Revision history for this message
Utkarsh Gupta (utkarsh) wrote :

Thank you, this was straightforward!

Sponsored:

$ dput ubuntu ../google-compute-engine-oslogin_20240701.00-0ubuntu1\~22.04.0_source.changes
Uploading google-compute-engine-oslogin using ftp to ubuntu (host: upload.ubuntu.com; directory: /ubuntu)
running supported-distribution: check whether the target distribution is currently supported (using distro-info)
{'allowed': ['release', 'proposed', 'backports', 'security'], 'known': ['release', 'proposed', 'updates', 'backports', 'security']}
running required-fields: check whether a field is present and non-empty in the changes file
running checksum: verify checksums before uploading
running suite-mismatch: check the target distribution for common errors
running check-debs: makes sure the upload contains a binary package
running gpg: check GnuPG signatures before the upload
Uploading google-compute-engine-oslogin_20240701.00-0ubuntu1~22.04.0.dsc
Uploading google-compute-engine-oslogin_20240701.00.orig.tar.gz
Uploading google-compute-engine-oslogin_20240701.00-0ubuntu1~22.04.0.debian.tar.xz
Uploading google-compute-engine-oslogin_20240701.00-0ubuntu1~22.04.0_source.buildinfo
Uploading google-compute-engine-oslogin_20240701.00-0ubuntu1~22.04.0_source.changes

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/OWNERS b/OWNERS
index edde10e..59fca61 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,14 +3,14 @@
33
4approvers:4approvers:
5 - a-crate5 - a-crate
6 - ajorg
6 - bkatyl7 - bkatyl
7 - chaitanyakulkarni288 - chaitanyakulkarni28
8 - dorileo9 - dorileo
9 - drewhli10 - drewhli
10 - elicriffield11 - elicriffield
12 - gaughen
11 - jjerger13 - jjerger
12 - karnvadaliya14 - karnvadaliya
13 - koln6715 - koln67
14 - quintonamore
15 - vorakl
16 - zmarano16 - zmarano
diff --git a/debian/changelog b/debian/changelog
index 99a260a..0066c96 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,45 @@
1google-compute-engine-oslogin (20240701.00-0ubuntu1~22.04.0) jammy; urgency=medium
2
3 * No-change rebuild for Jammy Jellyfish (LP: #2073166)
4
5 -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Fri, 26 Jul 2024 15:21:39 +0100
6
7google-compute-engine-oslogin (20240701.00-0ubuntu1) oracular; urgency=medium
8
9 [ Utkarsh Gupta ]
10 * d/links: Update links w/ respective .so shipped
11
12 [ Chloé 'kajiya' Smith ]
13 * New upstream version for upstream tag 20240320.00. (LP: #2073166)
14
15 -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Mon, 15 Jul 2024 17:56:01 +0100
16
17google-compute-engine-oslogin (20231004.00-0ubuntu5) oracular; urgency=medium
18
19 * d/p/0002-inherit-cflags.patch: inherit environment's build flags
20 (LP: #2071665).
21
22 -- Vladimir Petko <vladimir.petko@canonical.com> Tue, 02 Jul 2024 10:15:17 +1200
23
24google-compute-engine-oslogin (20231004.00-0ubuntu4) noble; urgency=medium
25
26 * No-change rebuild for CVE-2024-3094
27
28 -- William Grant <wgrant@ubuntu.com> Mon, 01 Apr 2024 16:49:52 +1100
29
30google-compute-engine-oslogin (20231004.00-0ubuntu3) noble; urgency=medium
31
32 * No-change rebuild against libcurl4t64
33
34 -- Steve Langasek <steve.langasek@ubuntu.com> Sat, 16 Mar 2024 06:24:53 +0000
35
36google-compute-engine-oslogin (20231004.00-0ubuntu2) noble; urgency=medium
37
38 * d/control: There must be a dependency on `google-guest-agent`
39 to match the (upstream) Google managed d/control file (LP: #2052438)
40
41 -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Thu, 01 Feb 2024 00:06:38 +0000
42
1google-compute-engine-oslogin (20231004.00-0ubuntu1~22.04.3) jammy; urgency=medium43google-compute-engine-oslogin (20231004.00-0ubuntu1~22.04.3) jammy; urgency=medium
244
3 * d/control: There must be a dependency on `google-guest-agent`45 * d/control: There must be a dependency on `google-guest-agent`
diff --git a/debian/links b/debian/links
index 12e449f..f5a4762 100644
--- a/debian/links
+++ b/debian/links
@@ -1,2 +1,2 @@
1lib/libnss_cache_oslogin-20231004.00.so lib/libnss_cache_oslogin.so.21lib/libnss_cache_oslogin-20240701.00.so lib/libnss_cache_oslogin.so.2
2lib/libnss_oslogin-20231004.00.so lib/libnss_oslogin.so.22lib/libnss_oslogin-20240701.00.so lib/libnss_oslogin.so.2
diff --git a/debian/patches/0002-inherit-cflags.patch b/debian/patches/0002-inherit-cflags.patch
3new file mode 1006443new file mode 100644
index 0000000..900f4e1
--- /dev/null
+++ b/debian/patches/0002-inherit-cflags.patch
@@ -0,0 +1,23 @@
1Description: use environment build flags.
2 The upstream makefile does not apply environment makefile flags.
3 This patch inherits the environment so that packaging-specific
4 build flags are applied.
5Author: Vladimir Petko <vladimir.petko@canonical.com>
6Bug: https://github.com/GoogleCloudPlatform/guest-oslogin/issues/139
7Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/google-compute-engine-oslogin/+bug/2071665
8Forwarded: no
9Last-Update: 2024-07-02
10
11--- a/src/Makefile
12+++ b/src/Makefile
13@@ -3,8 +3,8 @@
14
15 CPPFLAGS = -Iinclude -I/usr/include/json-c -I$(TOPDIR)/third_party/include
16 FLAGS = -fPIC -Wall -g
17-CFLAGS = $(FLAGS) -Wstrict-prototypes
18-CXXFLAGS = $(FLAGS)
19+CFLAGS := $(CFLAGS) $(FLAGS) -Wstrict-prototypes
20+CXXFLAGS := $(CXXFLAGS) $(FLAGS)
21
22 LDFLAGS = -shared -Wl,-z,defs -Wl,-soname,$(SONAME)
23 LDLIBS = -lcurl -ljson-c
diff --git a/debian/patches/series b/debian/patches/series
index 691fd0b..e023474 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
10001-set-LDFLAGS-to-prevent-undefs.patch10001-set-LDFLAGS-to-prevent-undefs.patch
20002-inherit-cflags.patch
diff --git a/packaging/google-compute-engine-oslogin.spec b/packaging/google-compute-engine-oslogin.spec
index 8f5eac2..5cf6bc6 100644
--- a/packaging/google-compute-engine-oslogin.spec
+++ b/packaging/google-compute-engine-oslogin.spec
@@ -67,6 +67,7 @@ make install DESTDIR=%{buildroot} LIBDIR=/%{_lib} VERSION=%{version} INSTALL_SEL
67/%{_lib}/libnss_cache_oslogin-%{version}.so67/%{_lib}/libnss_cache_oslogin-%{version}.so
68/%{_lib}/libnss_oslogin.so.268/%{_lib}/libnss_oslogin.so.2
69/%{_lib}/libnss_cache_oslogin.so.269/%{_lib}/libnss_cache_oslogin.so.2
70/%{_lib}/security/pam_oslogin_admin.so
70/%{_lib}/security/pam_oslogin_login.so71/%{_lib}/security/pam_oslogin_login.so
71/usr/bin/google_authorized_keys72/usr/bin/google_authorized_keys
72/usr/bin/google_authorized_keys_sk73/usr/bin/google_authorized_keys_sk
diff --git a/src/Makefile b/src/Makefile
index a633c7c..4f21719 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -21,12 +21,33 @@ CRONDIR = /etc/cron.d
21SYSTEMDDIR = /lib/systemd/system21SYSTEMDDIR = /lib/systemd/system
22PRESETDIR = /lib/systemd/system-preset22PRESETDIR = /lib/systemd/system-preset
2323
24DEST_LIBDIR = $(LIBDIR)
25DEST_BINDIR = $(BINDIR)
26DEST_PAMDIR = $(PAMDIR)
27DEST_MANDIR = $(MANDIR)
28DEST_SELINUX = /usr/share/selinux/packages
29DEST_CRONDIR = $(CRONDIR)
30DEST_SYSTEMDDIR = $(SYSTEMDDIR)
31DEST_PRESETDIR = $(PRESETDIR)
32
33ifneq ($(DESTDIR),)
34DEST_LIBDIR = $(DESTDIR)/$(LIBDIR)
35DEST_BINDIR = $(DESTDIR)/$(BINDIR)
36DEST_PAMDIR = $(DESTDIR)/$(PAMDIR)
37DEST_MANDIR = $(DESTDIR)/$(MANDIR)
38DEST_SELINUX = $(DESTDIR)/usr/share/selinux/packages
39DEST_CRONDIR = $(DESTDIR)/$(CRONDIR)
40DEST_SYSTEMDDIR = $(DESTDIR)/$(SYSTEMDDIR)
41DEST_PRESETDIR = $(DESTDIR)/$(PRESETDIR)
42endif
43
24NSS_OSLOGIN_SONAME = libnss_oslogin.so.244NSS_OSLOGIN_SONAME = libnss_oslogin.so.2
25NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.245NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2
2646
27NSS_OSLOGIN = libnss_oslogin-$(VERSION).so47NSS_OSLOGIN = libnss_oslogin-$(VERSION).so
28NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so48NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so
2949
50PAM_ADMIN = pam_oslogin_admin.so
30PAM_LOGIN = pam_oslogin_login.so51PAM_LOGIN = pam_oslogin_login.so
3152
32BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_keys_sk google_authorized_principals53BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_keys_sk google_authorized_principals
@@ -34,7 +55,7 @@ BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_key
34.PHONY: all clean install55.PHONY: all clean install
35.DEFAULT_GOAL := all56.DEFAULT_GOAL := all
3657
37all: $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(BINARIES)58all: $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(PAM_ADMIN) $(BINARIES)
3859
39clean:60clean:
40 rm -f $(BINARIES)61 rm -f $(BINARIES)
@@ -52,12 +73,15 @@ $(NSS_CACHE_OSLOGIN): nss/nss_cache_oslogin.o nss/compat/getpwent_r.o oslogin_ut
5273
53# PAM modules74# PAM modules
5475
55$(PAM_LOGIN): pam/pam_oslogin_login.o oslogin_sshca.o oslogin_utils.o include/oslogin_sshca.h76$(PAM_LOGIN): pam/pam_oslogin_login.o oslogin_sshca.o oslogin_utils.o
77 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
78
79$(PAM_ADMIN): pam/pam_oslogin_admin.o oslogin_sshca.o oslogin_utils.o
56 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)80 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
5781
58# Utilities.82# Utilities.
5983
60google_authorized_principals: authorized_principals/authorized_principals.o oslogin_utils.o oslogin_sshca.o include/oslogin_sshca.h84google_authorized_principals: authorized_principals/authorized_principals.o oslogin_utils.o oslogin_sshca.o
61 $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)85 $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
6286
63google_authorized_keys: authorized_keys/authorized_keys.o oslogin_utils.o87google_authorized_keys: authorized_keys/authorized_keys.o oslogin_utils.o
@@ -71,37 +95,37 @@ google_oslogin_nss_cache: cache_refresh/cache_refresh.o oslogin_utils.o
7195
72install: all96install: all
73 # Make dirs97 # Make dirs
74 install -d $(DESTDIR)$(LIBDIR)98 install -d $(DEST_LIBDIR)
75 install -d $(DESTDIR)$(PAMDIR)99 install -d $(DEST_PAMDIR)
76 install -d $(DESTDIR)$(BINDIR)100 install -d $(DEST_BINDIR)
77 install -d $(DESTDIR)$(MANDIR)/man8101 install -d $(DEST_MANDIR)/man8
78 # NSS modules102 # NSS modules
79 install -m 0644 -t $(DESTDIR)$(LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN)103 install -m 0644 -t $(DEST_LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN)
80 ln -sf $(NSS_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_OSLOGIN_SONAME)104 ln -sf $(NSS_OSLOGIN) $(DEST_LIBDIR)/$(NSS_OSLOGIN_SONAME)
81 ln -sf $(NSS_CACHE_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME)105 ln -sf $(NSS_CACHE_OSLOGIN) $(DEST_LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME)
82 # PAM modules106 # PAM modules
83 install -m 0644 -t $(DESTDIR)$(PAMDIR) $(PAM_LOGIN)107 install -m 0644 -t $(DEST_PAMDIR) $(PAM_LOGIN) $(PAM_ADMIN)
84 # Binaries108 # Binaries
85 install -m 0755 -t $(DESTDIR)$(BINDIR) $(BINARIES)109 install -m 0755 -t $(DEST_BINDIR) $(BINARIES)
86 # Manpages110 # Manpages
87 install -m 0644 -t $(DESTDIR)$(MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/nss-cache-oslogin.8111 install -m 0644 -t $(DEST_MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/nss-cache-oslogin.8
88 gzip -9f $(DESTDIR)$(MANDIR)/man8/nss-oslogin.8112 gzip -9f $(DEST_MANDIR)/man8/nss-oslogin.8
89 gzip -9f $(DESTDIR)$(MANDIR)/man8/nss-cache-oslogin.8113 gzip -9f $(DEST_MANDIR)/man8/nss-cache-oslogin.8
90 ln -sf nss-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz114 ln -sf nss-oslogin.8.gz $(DEST_MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz
91 ln -sf nss-cache-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz115 ln -sf nss-cache-oslogin.8.gz $(DEST_MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz
92ifdef INSTALL_SELINUX116ifdef INSTALL_SELINUX
93 # SELinux policy package117 # SELinux policy package
94 install -d $(DESTDIR)/usr/share/selinux/packages118 install -d $(DEST_SELINUX)
95 install -m 0644 -t $(DESTDIR)/usr/share/selinux/packages $(TOPDIR)/selinux/oslogin.pp119 install -m 0644 -t $(DEST_SELINUX) $(TOPDIR)/selinux/oslogin.pp
96endif120endif
97ifdef INSTALL_CRON121ifdef INSTALL_CRON
98 # Cache refresh cron122 # Cache refresh cron
99 install -d $(DESTDIR)$(CRONDIR)123 install -d $(DEST_CRONDIR)
100 install -m 0644 $(TOPDIR)/cron.d $(DESTDIR)$(CRONDIR)/google-compute-engine-oslogin124 install -m 0644 $(TOPDIR)/cron.d $(DEST_CRONDIR)/google-compute-engine-oslogin
101else125else
102 # Cache refresh systemd timer126 # Cache refresh systemd timer
103 install -d $(DESTDIR)$(SYSTEMDDIR)127 install -d $(DEST_SYSTEMDDIR)
104 install -m 0644 -t $(DESTDIR)$(SYSTEMDDIR) $(TOPDIR)/google-oslogin-cache.timer $(TOPDIR)/google-oslogin-cache.service128 install -m 0644 -t $(DEST_SYSTEMDDIR) $(TOPDIR)/google-oslogin-cache.timer $(TOPDIR)/google-oslogin-cache.service
105 install -d $(DESTDIR)$(PRESETDIR)129 install -d $(DEST_PRESETDIR)
106 install -m 0644 -t $(DESTDIR)$(PRESETDIR) $(TOPDIR)/90-google-compute-engine-oslogin.preset130 install -m 0644 -t $(DEST_PRESETDIR) $(TOPDIR)/90-google-compute-engine-oslogin.preset
107endif131endif
diff --git a/src/include/oslogin_utils.h b/src/include/oslogin_utils.h
index 368790e..e7c41fe 100644
--- a/src/include/oslogin_utils.h
+++ b/src/include/oslogin_utils.h
@@ -186,6 +186,9 @@ size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);
186bool HttpGet(const string& url, string* response, long* http_code);186bool HttpGet(const string& url, string* response, long* http_code);
187bool HttpPost(const string& url, const string& data, string* response,187bool HttpPost(const string& url, const string& data, string* response,
188 long* http_code);188 long* http_code);
189// Based on known MDS status codes returns whether the HTTP request
190// should be retried or not.
191bool ShouldRetry(long http_code);
189192
190// Returns whether user_name is a valid OsLogin user name.193// Returns whether user_name is a valid OsLogin user name.
191bool ValidateUserName(const string& user_name);194bool ValidateUserName(const string& user_name);
@@ -294,6 +297,11 @@ extern void SysLogErr(const char *fmt, ...);
294297
295// AuthoOptions wraps authorization options.298// AuthoOptions wraps authorization options.
296struct AuthOptions {299struct AuthOptions {
300 // admin_policy_required determines if a user is only authorized if admin
301 // policy is available for such a user. i.e. AuthorizeUser() should return
302 // false if adminLogin is not available.
303 bool admin_policy_required;
304
297 // security_key determines if the MDS "/users?..." should use305 // security_key determines if the MDS "/users?..." should use
298 // the view=securityKey parameter.306 // the view=securityKey parameter.
299 bool security_key;307 bool security_key;
diff --git a/src/oslogin_utils.cc b/src/oslogin_utils.cc
index f8bbf9c..aad560f 100644
--- a/src/oslogin_utils.cc
+++ b/src/oslogin_utils.cc
@@ -12,7 +12,7 @@
12// See the License for the specific language governing permissions and12// See the License for the specific language governing permissions and
13// limitations under the License.13// limitations under the License.
1414
15// Requires libcurl4-openssl-dev libjson0 and libjson0-dev15// Requires libcurl4-openssl-dev, libjson-c5, and libjson-c-dev
16#include <curl/curl.h>16#include <curl/curl.h>
17#include <errno.h>17#include <errno.h>
18#include <grp.h>18#include <grp.h>
@@ -48,7 +48,10 @@
48using std::string;48using std::string;
4949
50// Maximum number of retries for HTTP requests.50// Maximum number of retries for HTTP requests.
51const int kMaxRetries = 1;51const int kMaxRetries = 3;
52
53// Backoff duration 1 sec between retries.
54const int kBackoffDuration = 1;
5255
53// Regex for validating user names.56// Regex for validating user names.
54static const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$";57static const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$";
@@ -189,11 +192,29 @@ bool NssCache::GetNextGroup(BufferManager* buf, struct group* result, int* errno
189 return ParseJsonToGroup(cached_passwd, result, buf, errnop);192 return ParseJsonToGroup(cached_passwd, result, buf, errnop);
190}193}
191194
195// ParseJsonRoot is declared early here, away from the other parsing functions
196// found later (in the "JSON Parsing" section), so LoadJsonUsersToCache can
197// take advantage of the improved error handling ParseJsonRoot offers.
198json_object* ParseJsonRoot(const string& json) {
199 json_object* root = NULL;
200 struct json_tokener* tok = json_tokener_new();
201
202 root = json_tokener_parse_ex(tok, json.c_str(), -1);
203 if (root == NULL) {
204 enum json_tokener_error jerr = json_tokener_get_error(tok);
205 string error_message = json_tokener_error_desc(jerr);
206 SysLogErr("Failed to parse root JSON element: \"%s\", from input \"%s\"",
207 error_message, json);
208 }
209
210 json_tokener_free(tok);
211 return root;
212}
213
192bool NssCache::LoadJsonUsersToCache(string response) {214bool NssCache::LoadJsonUsersToCache(string response) {
193 Reset();215 Reset();
194216
195 json_object* root = NULL;217 json_object* root = ParseJsonRoot(response);
196 root = json_tokener_parse(response.c_str());
197 if (root == NULL) {218 if (root == NULL) {
198 return false;219 return false;
199 }220 }
@@ -392,6 +413,22 @@ size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp) {
392 return 0;413 return 0;
393}414}
394415
416bool ShouldRetry(long http_code) {
417 if (http_code == 200) {
418 // Request returned successfully, no need to retry.
419 return false;
420 }
421 if (http_code == 404) {
422 // Metadata key does not exist, no point of retrying.
423 return false;
424 }
425 if (http_code == 400) {
426 // Request parameters are bad, no point of retrying.
427 return false;
428 }
429 return true;
430}
431
395bool HttpDo(const string& url, const string& data, string* response, long* http_code) {432bool HttpDo(const string& url, const string& data, string* response, long* http_code) {
396 if (response == NULL || http_code == NULL) {433 if (response == NULL || http_code == NULL) {
397 return false;434 return false;
@@ -410,6 +447,10 @@ bool HttpDo(const string& url, const string& data, string* response, long* http_
410 return false;447 return false;
411 }448 }
412 do {449 do {
450 // Apply backoff strategy before retrying.
451 if (retry_count > 0) {
452 sleep(kBackoffDuration);
453 }
413 response_stream.str("");454 response_stream.str("");
414 response_stream.clear();455 response_stream.clear();
415 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);456 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
@@ -428,7 +469,7 @@ bool HttpDo(const string& url, const string& data, string* response, long* http_
428 return false;469 return false;
429 }470 }
430 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code);471 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code);
431 } while (retry_count++ < kMaxRetries && *http_code == 500);472 } while (retry_count++ < kMaxRetries && ShouldRetry(*http_code));
432 curl_slist_free_all(header_list);473 curl_slist_free_all(header_list);
433 }474 }
434 *response = response_stream.str();475 *response = response_stream.str();
@@ -506,14 +547,12 @@ bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop) {
506// ----------------- JSON Parsing -----------------547// ----------------- JSON Parsing -----------------
507548
508bool ParseJsonToUsers(const string& json, std::vector<string>* result) {549bool ParseJsonToUsers(const string& json, std::vector<string>* result) {
509 json_object* root = NULL;
510 root = json_tokener_parse(json.c_str());
511 if (root == NULL) {
512 return false;
513 }
514
515 bool ret = false;550 bool ret = false;
516551
552 json_object* root = ParseJsonRoot(json);
553 if (root == NULL) {
554 return ret;
555 }
517 json_object* users = NULL;556 json_object* users = NULL;
518 if (!json_object_object_get_ex(root, "usernames", &users)) {557 if (!json_object_object_get_ex(root, "usernames", &users)) {
519 ret = true; // means no users, not invalid.558 ret = true; // means no users, not invalid.
@@ -535,19 +574,22 @@ cleanup:
535}574}
536575
537bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {576bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {
538 json_object* root = NULL;
539 root = json_tokener_parse(json.c_str());
540 if (root == NULL) {
541 return false;
542 }
543
544 bool ret = false;577 bool ret = false;
545578
546 json_object* groups = NULL;579 json_object* root = ParseJsonRoot(json);
580 if (root == NULL) {
581 return ret;
582 }
583 json_object* groups;
584 json_type groupType;
547 if (!json_object_object_get_ex(root, "posixGroups", &groups)) {585 if (!json_object_object_get_ex(root, "posixGroups", &groups)) {
586 SysLogErr("failed to parse POSIX groups from \"%s\"", json);
548 goto cleanup;587 goto cleanup;
549 }588 }
550 if (json_object_get_type(groups) != json_type_array) {589 groupType = json_object_get_type(groups);
590 if (groupType != json_type_array) {
591 SysLogErr("parsed unexpected type for field \"posixGroups\"; "
592 "want a list, got %s", groupType);
551 goto cleanup;593 goto cleanup;
552 }594 }
553 for (int idx = 0; idx < (int)json_object_array_length(groups); idx++) {595 for (int idx = 0; idx < (int)json_object_array_length(groups); idx++) {
@@ -555,11 +597,12 @@ bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {
555597
556 json_object* gid;598 json_object* gid;
557 if (!json_object_object_get_ex(group, "gid", &gid)) {599 if (!json_object_object_get_ex(group, "gid", &gid)) {
600 SysLogErr("failed to parse gid from group %s", json_object_get_string(group));
558 goto cleanup;601 goto cleanup;
559 }602 }
560
561 json_object* name;603 json_object* name;
562 if (!json_object_object_get_ex(group, "name", &name)) {604 if (!json_object_object_get_ex(group, "name", &name)) {
605 SysLogErr("failed to parse name from group %s", json_object_get_string(group));
563 goto cleanup;606 goto cleanup;
564 }607 }
565608
@@ -589,22 +632,19 @@ cleanup:
589632
590bool ParseJsonToGroup(const string& json, struct group* result, BufferManager*633bool ParseJsonToGroup(const string& json, struct group* result, BufferManager*
591 buf, int* errnop) {634 buf, int* errnop) {
635 bool ret = false;
592 *errnop = EINVAL;636 *errnop = EINVAL;
593 int gr_gid = 65535;637 int gr_gid = 65535;
594638
595 json_object* group = NULL;639 json_object* group = ParseJsonRoot(json);
596 group = json_tokener_parse(json.c_str());
597 if (group == NULL) {640 if (group == NULL) {
598 return false;641 return false;
599 }642 }
600643
601 bool ret = false;
602
603 json_object* gid;644 json_object* gid;
604 if (!json_object_object_get_ex(group, "gid", &gid)) {645 if (!json_object_object_get_ex(group, "gid", &gid)) {
605 goto cleanup;646 goto cleanup;
606 }647 }
607
608 json_object* name;648 json_object* name;
609 if (!json_object_object_get_ex(group, "name", &name)) {649 if (!json_object_object_get_ex(group, "name", &name)) {
610 goto cleanup;650 goto cleanup;
@@ -631,16 +671,13 @@ cleanup:
631671
632std::vector<string> ParseJsonToSshKeys(const string& json) {672std::vector<string> ParseJsonToSshKeys(const string& json) {
633 std::vector<string> result;673 std::vector<string> result;
634 json_object* ssh_public_keys = NULL;674 json_object* root = ParseJsonRoot(json);
635
636 json_object* root = NULL;
637 root = json_tokener_parse(json.c_str());
638 if (root == NULL) {675 if (root == NULL) {
639 return result;676 return result;
640 }677 }
641678
642 // Locate the sshPublicKeys object.679 // Locate the sshPublicKeys object.
643 json_object* login_profiles = NULL;680 json_object* login_profiles;
644 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {681 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
645 goto cleanup;682 goto cleanup;
646 }683 }
@@ -649,6 +686,7 @@ std::vector<string> ParseJsonToSshKeys(const string& json) {
649 }686 }
650 login_profiles = json_object_array_get_idx(login_profiles, 0);687 login_profiles = json_object_array_get_idx(login_profiles, 0);
651688
689 json_object* ssh_public_keys;
652 if (!json_object_object_get_ex(login_profiles, "sshPublicKeys", &ssh_public_keys)) {690 if (!json_object_object_get_ex(login_profiles, "sshPublicKeys", &ssh_public_keys)) {
653 goto cleanup;691 goto cleanup;
654 }692 }
@@ -701,16 +739,14 @@ cleanup:
701739
702std::vector<string> ParseJsonToSshKeysSk(const string& json) {740std::vector<string> ParseJsonToSshKeysSk(const string& json) {
703 std::vector<string> result;741 std::vector<string> result;
704 json_object* security_keys = NULL;
705742
706 json_object* root = NULL;743 json_object* root = ParseJsonRoot(json);
707 root = json_tokener_parse(json.c_str());
708 if (root == NULL) {744 if (root == NULL) {
709 return result;745 return result;
710 }746 }
711747
712 // Locate the securityKeys array.748 // Locate the securityKeys array.
713 json_object* login_profiles = NULL;749 json_object* login_profiles;
714 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {750 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
715 goto cleanup;751 goto cleanup;
716 }752 }
@@ -720,9 +756,11 @@ std::vector<string> ParseJsonToSshKeysSk(const string& json) {
720756
721 login_profiles = json_object_array_get_idx(login_profiles, 0);757 login_profiles = json_object_array_get_idx(login_profiles, 0);
722758
759 json_object* security_keys;
723 if (!json_object_object_get_ex(login_profiles, "securityKeys", &security_keys)) {760 if (!json_object_object_get_ex(login_profiles, "securityKeys", &security_keys)) {
724 goto cleanup;761 goto cleanup;
725 }762 }
763
726 if (json_object_get_type(security_keys) != json_type_array) {764 if (json_object_get_type(security_keys) != json_type_array) {
727 goto cleanup;765 goto cleanup;
728 }766 }
@@ -757,19 +795,18 @@ cleanup:
757795
758bool ParseJsonToPasswd(const string& json, struct passwd* result, BufferManager*796bool ParseJsonToPasswd(const string& json, struct passwd* result, BufferManager*
759 buf, int* errnop) {797 buf, int* errnop) {
798 bool ret = false;
760 *errnop = EINVAL;799 *errnop = EINVAL;
761 json_object* root = NULL;800 json_object* root = NULL;
762 json_object* origroot = NULL;801 json_object* origroot = NULL;
763802
764 origroot = root = json_tokener_parse(json.c_str());803 origroot = root = ParseJsonRoot(json);
765 if (root == NULL) {804 if (root == NULL) {
766 return false;805 return false;
767 }806 }
768807
769 bool ret = false;808 json_object* posix_accounts;
770 json_object* posix_accounts = NULL;809 json_object* login_profiles;
771
772 json_object* login_profiles = NULL;
773 // If this is called from getpwent_r, loginProfiles won't be in the response.810 // If this is called from getpwent_r, loginProfiles won't be in the response.
774 if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {811 if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
775 if (json_object_get_type(login_profiles) != json_type_array) {812 if (json_object_get_type(login_profiles) != json_type_array) {
@@ -888,17 +925,16 @@ bool AddUsersToGroup(std::vector<string> users, struct group* result,
888}925}
889926
890bool ParseJsonToEmail(const string& json, string* email) {927bool ParseJsonToEmail(const string& json, string* email) {
891 json_object* root = NULL;928 bool ret = false;
892 root = json_tokener_parse(json.c_str());929
930 json_object* root = ParseJsonRoot(json);
893 if (root == NULL) {931 if (root == NULL) {
894 return false;932 return ret;
895 }933 }
896934
897 bool ret = false;
898 json_object* json_email = NULL;
899
900 // Locate the email object.935 // Locate the email object.
901 json_object* login_profiles = NULL;936 json_object* login_profiles;
937 json_object* json_email;
902 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {938 if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
903 goto cleanup;939 goto cleanup;
904 }940 }
@@ -918,8 +954,7 @@ cleanup:
918}954}
919955
920bool ParseJsonToSuccess(const string& json) {956bool ParseJsonToSuccess(const string& json) {
921 json_object* root = NULL;957 json_object* root = ParseJsonRoot(json);
922 root = json_tokener_parse(json.c_str());
923 if (root == NULL) {958 if (root == NULL) {
924 return false;959 return false;
925 }960 }
@@ -934,17 +969,15 @@ bool ParseJsonToSuccess(const string& json) {
934}969}
935970
936bool ParseJsonToKey(const string& json, const string& key, string* response) {971bool ParseJsonToKey(const string& json, const string& key, string* response) {
937 json_object* root = NULL;972 bool ret = false;
938 root = json_tokener_parse(json.c_str());973
974 json_object* root = ParseJsonRoot(json);
939 if (root == NULL) {975 if (root == NULL) {
940 return false;976 return ret;
941 }977 }
942978
943 bool ret = false;
944 json_object* json_response = NULL;979 json_object* json_response = NULL;
945 const char* c_response = NULL;980 const char* c_response = NULL;
946
947
948 if (!json_object_object_get_ex(root, key.c_str(), &json_response)) {981 if (!json_object_object_get_ex(root, key.c_str(), &json_response)) {
949 goto cleanup;982 goto cleanup;
950 }983 }
@@ -962,13 +995,13 @@ cleanup:
962}995}
963996
964bool ParseJsonToChallenges(const string& json, std::vector<Challenge>* challenges) {997bool ParseJsonToChallenges(const string& json, std::vector<Challenge>* challenges) {
965 json_object* root = NULL;998 bool ret = false;
966 root = json_tokener_parse(json.c_str());999
1000 json_object* root = ParseJsonRoot(json);
967 if (root == NULL) {1001 if (root == NULL) {
968 return false;1002 return ret;
969 }1003 }
9701004
971 bool ret = false;
972 json_object* challengeId = NULL;1005 json_object* challengeId = NULL;
973 json_object* challengeType = NULL;1006 json_object* challengeType = NULL;
974 json_object* challengeStatus = NULL;1007 json_object* challengeStatus = NULL;
@@ -1260,18 +1293,18 @@ static bool ApplyPolicy(const char *user_name, string email, const char *policy,
1260 long http_code = 0;1293 long http_code = 0;
1261 // Invalid user, just leave from here - the principal will not be allowed/authorized.1294 // Invalid user, just leave from here - the principal will not be allowed/authorized.
1262 if (!HttpGet(url.str(), &response, &http_code)) {1295 if (!HttpGet(url.str(), &response, &http_code)) {
1263 SysLogErr("Failed to validate organization user %s has login permission.", user_name);1296 SysLogErr("Failed to validate that OS Login user %s has %s permission.", user_name, policy);
1264 return false;1297 return false;
1265 }1298 }
12661299
1267 if (http_code != 200) {1300 if (http_code != 200) {
1268 SysLogErr("Failed to validate organization user %s has login permission, "1301 SysLogErr("Failed to validate that OS Login user %s has %s permission; "
1269 "got HTTP response code: %lu", user_name, http_code);1302 "got HTTP response code: %lu", user_name, policy, http_code);
1270 return false;1303 return false;
1271 }1304 }
12721305
1273 if (!ParseJsonToSuccess(response)) {1306 if (!ParseJsonToSuccess(response)) {
1274 SysLogErr("Organization user %s does not have login permission.", user_name);1307 SysLogErr("OS Login user %s does not have %s permission.", user_name, policy);
1275 return false;1308 return false;
1276 }1309 }
12771310
@@ -1369,6 +1402,9 @@ bool AuthorizeUser(const char *user_name, struct AuthOptions opts, string *user_
1369 }1402 }
1370 } else {1403 } else {
1371 remove(sudoers_filename.c_str());1404 remove(sudoers_filename.c_str());
1405 if (opts.admin_policy_required) {
1406 return false;
1407 }
1372 }1408 }
13731409
1374 return true;1410 return true;
diff --git a/src/pam/pam_oslogin_admin.cc b/src/pam/pam_oslogin_admin.cc
1375new file mode 1006441411new file mode 100644
index 0000000..06bb10b
--- /dev/null
+++ b/src/pam/pam_oslogin_admin.cc
@@ -0,0 +1,53 @@
1// Copyright 2024 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <security/pam_modules.h>
16
17#include <compat.h>
18#include <oslogin_utils.h>
19
20using std::string;
21
22using oslogin_utils::AuthOptions;
23
24extern "C" {
25
26// pm_sm_acct_mgmt is the account management PAM implementation for admin users (or users
27// with the proper loginAdmin policy). This account management module is intended for custom
28// configuration handling only, where users need a way to in their stack configurations to
29// differentiate a OS Login user. The Google Guest Agent will not manage the lifecycle of
30// this module, it will not add this to the stack as part of the standard/default configuration
31// set.
32PAM_EXTERN int
33pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) {
34 struct AuthOptions opts;
35 const char *user_name;
36 string user_response;
37
38 if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
39 PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
40 return PAM_PERM_DENIED;
41 }
42
43 opts = { 0 };
44 opts.admin_policy_required = true;
45
46 if (!AuthorizeUser(user_name, opts, &user_response)) {
47 return PAM_PERM_DENIED;
48 }
49
50 return PAM_SUCCESS;
51}
52
53}
diff --git a/src/pam/pam_oslogin_login.cc b/src/pam/pam_oslogin_login.cc
index ca41ed3..5d863d2 100644
--- a/src/pam/pam_oslogin_login.cc
+++ b/src/pam/pam_oslogin_login.cc
@@ -22,6 +22,7 @@
22#include <compat.h>22#include <compat.h>
23#include <oslogin_utils.h>23#include <oslogin_utils.h>
2424
25using oslogin_utils::AuthOptions;
25using oslogin_utils::ContinueSession;26using oslogin_utils::ContinueSession;
26using oslogin_utils::GetUser;27using oslogin_utils::GetUser;
27using oslogin_utils::ParseJsonToChallenges;28using oslogin_utils::ParseJsonToChallenges;
@@ -32,6 +33,32 @@ using oslogin_utils::ValidateUserName;
3233
33extern "C" {34extern "C" {
3435
36// pm_sm_acct_mgmt is the account management PAM implementation for non-admin users (or users
37// without the proper loginAdmin policy). This account management module is intended for custom
38// configuration handling only, where users need a way to in their stack configurations to
39// differentiate a OS Login user. The Google Guest Agent will not manage the lifecycle of
40// this module, it will not add this to the stack as part of the standard/default configuration
41// set.
42PAM_EXTERN int
43pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) {
44 struct AuthOptions opts;
45 const char *user_name;
46 string user_response;
47
48 if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
49 PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
50 return PAM_PERM_DENIED;
51 }
52
53 opts = { 0 };
54
55 if (!AuthorizeUser(user_name, opts, &user_response)) {
56 return PAM_PERM_DENIED;
57 }
58
59 return PAM_SUCCESS;
60}
61
35PAM_EXTERN int62PAM_EXTERN int
36pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv) {63pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv) {
37 return PAM_SUCCESS;64 return PAM_SUCCESS;
diff --git a/test/oslogin_utils_test.cc b/test/oslogin_utils_test.cc
index 3451f61..0646a34 100644
--- a/test/oslogin_utils_test.cc
+++ b/test/oslogin_utils_test.cc
@@ -460,6 +460,13 @@ TEST(GetGroupByTest, GetGroupByGIDSucceeds) {
460 ASSERT_EQ(errnop, 0);460 ASSERT_EQ(errnop, 0);
461}461}
462462
463TEST(CurlClient, RetryLogic) {
464 ASSERT_FALSE(ShouldRetry(200));
465 ASSERT_FALSE(ShouldRetry(404));
466 ASSERT_FALSE(ShouldRetry(400));
467 ASSERT_TRUE(ShouldRetry(429));
468}
469
463TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) {470TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) {
464 string test_user =471 string test_user =
465 "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["472 "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["

Subscribers

People subscribed via source and target branches