Merge ~kajiya/+git/google-compute-engine-oslogin:update-jammy-to-20240701.00 into ~ubuntu-core-dev/+git/google-compute-engine-oslogin:ubuntu/jammy
- Git
- lp:~kajiya/+git/google-compute-engine-oslogin
- update-jammy-to-20240701.00
- Merge into 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) |
||||||||
Related bugs: |
|
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-
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/OWNERS b/OWNERS | |||
2 | index edde10e..59fca61 100644 | |||
3 | --- a/OWNERS | |||
4 | +++ b/OWNERS | |||
5 | @@ -3,14 +3,14 @@ | |||
6 | 3 | 3 | ||
7 | 4 | approvers: | 4 | approvers: |
8 | 5 | - a-crate | 5 | - a-crate |
9 | 6 | - ajorg | ||
10 | 6 | - bkatyl | 7 | - bkatyl |
11 | 7 | - chaitanyakulkarni28 | 8 | - chaitanyakulkarni28 |
12 | 8 | - dorileo | 9 | - dorileo |
13 | 9 | - drewhli | 10 | - drewhli |
14 | 10 | - elicriffield | 11 | - elicriffield |
15 | 12 | - gaughen | ||
16 | 11 | - jjerger | 13 | - jjerger |
17 | 12 | - karnvadaliya | 14 | - karnvadaliya |
18 | 13 | - koln67 | 15 | - koln67 |
19 | 14 | - quintonamore | ||
20 | 15 | - vorakl | ||
21 | 16 | - zmarano | 16 | - zmarano |
22 | diff --git a/debian/changelog b/debian/changelog | |||
23 | index 99a260a..0066c96 100644 | |||
24 | --- a/debian/changelog | |||
25 | +++ b/debian/changelog | |||
26 | @@ -1,3 +1,45 @@ | |||
27 | 1 | google-compute-engine-oslogin (20240701.00-0ubuntu1~22.04.0) jammy; urgency=medium | ||
28 | 2 | |||
29 | 3 | * No-change rebuild for Jammy Jellyfish (LP: #2073166) | ||
30 | 4 | |||
31 | 5 | -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Fri, 26 Jul 2024 15:21:39 +0100 | ||
32 | 6 | |||
33 | 7 | google-compute-engine-oslogin (20240701.00-0ubuntu1) oracular; urgency=medium | ||
34 | 8 | |||
35 | 9 | [ Utkarsh Gupta ] | ||
36 | 10 | * d/links: Update links w/ respective .so shipped | ||
37 | 11 | |||
38 | 12 | [ Chloé 'kajiya' Smith ] | ||
39 | 13 | * New upstream version for upstream tag 20240320.00. (LP: #2073166) | ||
40 | 14 | |||
41 | 15 | -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Mon, 15 Jul 2024 17:56:01 +0100 | ||
42 | 16 | |||
43 | 17 | google-compute-engine-oslogin (20231004.00-0ubuntu5) oracular; urgency=medium | ||
44 | 18 | |||
45 | 19 | * d/p/0002-inherit-cflags.patch: inherit environment's build flags | ||
46 | 20 | (LP: #2071665). | ||
47 | 21 | |||
48 | 22 | -- Vladimir Petko <vladimir.petko@canonical.com> Tue, 02 Jul 2024 10:15:17 +1200 | ||
49 | 23 | |||
50 | 24 | google-compute-engine-oslogin (20231004.00-0ubuntu4) noble; urgency=medium | ||
51 | 25 | |||
52 | 26 | * No-change rebuild for CVE-2024-3094 | ||
53 | 27 | |||
54 | 28 | -- William Grant <wgrant@ubuntu.com> Mon, 01 Apr 2024 16:49:52 +1100 | ||
55 | 29 | |||
56 | 30 | google-compute-engine-oslogin (20231004.00-0ubuntu3) noble; urgency=medium | ||
57 | 31 | |||
58 | 32 | * No-change rebuild against libcurl4t64 | ||
59 | 33 | |||
60 | 34 | -- Steve Langasek <steve.langasek@ubuntu.com> Sat, 16 Mar 2024 06:24:53 +0000 | ||
61 | 35 | |||
62 | 36 | google-compute-engine-oslogin (20231004.00-0ubuntu2) noble; urgency=medium | ||
63 | 37 | |||
64 | 38 | * d/control: There must be a dependency on `google-guest-agent` | ||
65 | 39 | to match the (upstream) Google managed d/control file (LP: #2052438) | ||
66 | 40 | |||
67 | 41 | -- Chloé 'kajiya' Smith <chloe.smith@canonical.com> Thu, 01 Feb 2024 00:06:38 +0000 | ||
68 | 42 | |||
69 | 1 | google-compute-engine-oslogin (20231004.00-0ubuntu1~22.04.3) jammy; urgency=medium | 43 | google-compute-engine-oslogin (20231004.00-0ubuntu1~22.04.3) jammy; urgency=medium |
70 | 2 | 44 | ||
71 | 3 | * d/control: There must be a dependency on `google-guest-agent` | 45 | * d/control: There must be a dependency on `google-guest-agent` |
72 | diff --git a/debian/links b/debian/links | |||
73 | index 12e449f..f5a4762 100644 | |||
74 | --- a/debian/links | |||
75 | +++ b/debian/links | |||
76 | @@ -1,2 +1,2 @@ | |||
79 | 1 | lib/libnss_cache_oslogin-20231004.00.so lib/libnss_cache_oslogin.so.2 | 1 | lib/libnss_cache_oslogin-20240701.00.so lib/libnss_cache_oslogin.so.2 |
80 | 2 | lib/libnss_oslogin-20231004.00.so lib/libnss_oslogin.so.2 | 2 | lib/libnss_oslogin-20240701.00.so lib/libnss_oslogin.so.2 |
81 | diff --git a/debian/patches/0002-inherit-cflags.patch b/debian/patches/0002-inherit-cflags.patch | |||
82 | 3 | new file mode 100644 | 3 | new file mode 100644 |
83 | index 0000000..900f4e1 | |||
84 | --- /dev/null | |||
85 | +++ b/debian/patches/0002-inherit-cflags.patch | |||
86 | @@ -0,0 +1,23 @@ | |||
87 | 1 | Description: use environment build flags. | ||
88 | 2 | The upstream makefile does not apply environment makefile flags. | ||
89 | 3 | This patch inherits the environment so that packaging-specific | ||
90 | 4 | build flags are applied. | ||
91 | 5 | Author: Vladimir Petko <vladimir.petko@canonical.com> | ||
92 | 6 | Bug: https://github.com/GoogleCloudPlatform/guest-oslogin/issues/139 | ||
93 | 7 | Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/google-compute-engine-oslogin/+bug/2071665 | ||
94 | 8 | Forwarded: no | ||
95 | 9 | Last-Update: 2024-07-02 | ||
96 | 10 | |||
97 | 11 | --- a/src/Makefile | ||
98 | 12 | +++ b/src/Makefile | ||
99 | 13 | @@ -3,8 +3,8 @@ | ||
100 | 14 | |||
101 | 15 | CPPFLAGS = -Iinclude -I/usr/include/json-c -I$(TOPDIR)/third_party/include | ||
102 | 16 | FLAGS = -fPIC -Wall -g | ||
103 | 17 | -CFLAGS = $(FLAGS) -Wstrict-prototypes | ||
104 | 18 | -CXXFLAGS = $(FLAGS) | ||
105 | 19 | +CFLAGS := $(CFLAGS) $(FLAGS) -Wstrict-prototypes | ||
106 | 20 | +CXXFLAGS := $(CXXFLAGS) $(FLAGS) | ||
107 | 21 | |||
108 | 22 | LDFLAGS = -shared -Wl,-z,defs -Wl,-soname,$(SONAME) | ||
109 | 23 | LDLIBS = -lcurl -ljson-c | ||
110 | diff --git a/debian/patches/series b/debian/patches/series | |||
111 | index 691fd0b..e023474 100644 | |||
112 | --- a/debian/patches/series | |||
113 | +++ b/debian/patches/series | |||
114 | @@ -1 +1,2 @@ | |||
115 | 1 | 0001-set-LDFLAGS-to-prevent-undefs.patch | 1 | 0001-set-LDFLAGS-to-prevent-undefs.patch |
116 | 2 | 0002-inherit-cflags.patch | ||
117 | diff --git a/packaging/google-compute-engine-oslogin.spec b/packaging/google-compute-engine-oslogin.spec | |||
118 | index 8f5eac2..5cf6bc6 100644 | |||
119 | --- a/packaging/google-compute-engine-oslogin.spec | |||
120 | +++ b/packaging/google-compute-engine-oslogin.spec | |||
121 | @@ -67,6 +67,7 @@ make install DESTDIR=%{buildroot} LIBDIR=/%{_lib} VERSION=%{version} INSTALL_SEL | |||
122 | 67 | /%{_lib}/libnss_cache_oslogin-%{version}.so | 67 | /%{_lib}/libnss_cache_oslogin-%{version}.so |
123 | 68 | /%{_lib}/libnss_oslogin.so.2 | 68 | /%{_lib}/libnss_oslogin.so.2 |
124 | 69 | /%{_lib}/libnss_cache_oslogin.so.2 | 69 | /%{_lib}/libnss_cache_oslogin.so.2 |
125 | 70 | /%{_lib}/security/pam_oslogin_admin.so | ||
126 | 70 | /%{_lib}/security/pam_oslogin_login.so | 71 | /%{_lib}/security/pam_oslogin_login.so |
127 | 71 | /usr/bin/google_authorized_keys | 72 | /usr/bin/google_authorized_keys |
128 | 72 | /usr/bin/google_authorized_keys_sk | 73 | /usr/bin/google_authorized_keys_sk |
129 | diff --git a/src/Makefile b/src/Makefile | |||
130 | index a633c7c..4f21719 100644 | |||
131 | --- a/src/Makefile | |||
132 | +++ b/src/Makefile | |||
133 | @@ -21,12 +21,33 @@ CRONDIR = /etc/cron.d | |||
134 | 21 | SYSTEMDDIR = /lib/systemd/system | 21 | SYSTEMDDIR = /lib/systemd/system |
135 | 22 | PRESETDIR = /lib/systemd/system-preset | 22 | PRESETDIR = /lib/systemd/system-preset |
136 | 23 | 23 | ||
137 | 24 | DEST_LIBDIR = $(LIBDIR) | ||
138 | 25 | DEST_BINDIR = $(BINDIR) | ||
139 | 26 | DEST_PAMDIR = $(PAMDIR) | ||
140 | 27 | DEST_MANDIR = $(MANDIR) | ||
141 | 28 | DEST_SELINUX = /usr/share/selinux/packages | ||
142 | 29 | DEST_CRONDIR = $(CRONDIR) | ||
143 | 30 | DEST_SYSTEMDDIR = $(SYSTEMDDIR) | ||
144 | 31 | DEST_PRESETDIR = $(PRESETDIR) | ||
145 | 32 | |||
146 | 33 | ifneq ($(DESTDIR),) | ||
147 | 34 | DEST_LIBDIR = $(DESTDIR)/$(LIBDIR) | ||
148 | 35 | DEST_BINDIR = $(DESTDIR)/$(BINDIR) | ||
149 | 36 | DEST_PAMDIR = $(DESTDIR)/$(PAMDIR) | ||
150 | 37 | DEST_MANDIR = $(DESTDIR)/$(MANDIR) | ||
151 | 38 | DEST_SELINUX = $(DESTDIR)/usr/share/selinux/packages | ||
152 | 39 | DEST_CRONDIR = $(DESTDIR)/$(CRONDIR) | ||
153 | 40 | DEST_SYSTEMDDIR = $(DESTDIR)/$(SYSTEMDDIR) | ||
154 | 41 | DEST_PRESETDIR = $(DESTDIR)/$(PRESETDIR) | ||
155 | 42 | endif | ||
156 | 43 | |||
157 | 24 | NSS_OSLOGIN_SONAME = libnss_oslogin.so.2 | 44 | NSS_OSLOGIN_SONAME = libnss_oslogin.so.2 |
158 | 25 | NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2 | 45 | NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2 |
159 | 26 | 46 | ||
160 | 27 | NSS_OSLOGIN = libnss_oslogin-$(VERSION).so | 47 | NSS_OSLOGIN = libnss_oslogin-$(VERSION).so |
161 | 28 | NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so | 48 | NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so |
162 | 29 | 49 | ||
163 | 50 | PAM_ADMIN = pam_oslogin_admin.so | ||
164 | 30 | PAM_LOGIN = pam_oslogin_login.so | 51 | PAM_LOGIN = pam_oslogin_login.so |
165 | 31 | 52 | ||
166 | 32 | BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_keys_sk google_authorized_principals | 53 | BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_keys_sk google_authorized_principals |
167 | @@ -34,7 +55,7 @@ BINARIES = google_oslogin_nss_cache google_authorized_keys google_authorized_key | |||
168 | 34 | .PHONY: all clean install | 55 | .PHONY: all clean install |
169 | 35 | .DEFAULT_GOAL := all | 56 | .DEFAULT_GOAL := all |
170 | 36 | 57 | ||
172 | 37 | all: $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(BINARIES) | 58 | all: $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(PAM_ADMIN) $(BINARIES) |
173 | 38 | 59 | ||
174 | 39 | clean: | 60 | clean: |
175 | 40 | rm -f $(BINARIES) | 61 | rm -f $(BINARIES) |
176 | @@ -52,12 +73,15 @@ $(NSS_CACHE_OSLOGIN): nss/nss_cache_oslogin.o nss/compat/getpwent_r.o oslogin_ut | |||
177 | 52 | 73 | ||
178 | 53 | # PAM modules | 74 | # PAM modules |
179 | 54 | 75 | ||
181 | 55 | $(PAM_LOGIN): pam/pam_oslogin_login.o oslogin_sshca.o oslogin_utils.o include/oslogin_sshca.h | 76 | $(PAM_LOGIN): pam/pam_oslogin_login.o oslogin_sshca.o oslogin_utils.o |
182 | 77 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS) | ||
183 | 78 | |||
184 | 79 | $(PAM_ADMIN): pam/pam_oslogin_admin.o oslogin_sshca.o oslogin_utils.o | ||
185 | 56 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS) | 80 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS) |
186 | 57 | 81 | ||
187 | 58 | # Utilities. | 82 | # Utilities. |
188 | 59 | 83 | ||
190 | 60 | google_authorized_principals: authorized_principals/authorized_principals.o oslogin_utils.o oslogin_sshca.o include/oslogin_sshca.h | 84 | google_authorized_principals: authorized_principals/authorized_principals.o oslogin_utils.o oslogin_sshca.o |
191 | 61 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) | 85 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS) |
192 | 62 | 86 | ||
193 | 63 | google_authorized_keys: authorized_keys/authorized_keys.o oslogin_utils.o | 87 | google_authorized_keys: authorized_keys/authorized_keys.o oslogin_utils.o |
194 | @@ -71,37 +95,37 @@ google_oslogin_nss_cache: cache_refresh/cache_refresh.o oslogin_utils.o | |||
195 | 71 | 95 | ||
196 | 72 | install: all | 96 | install: all |
197 | 73 | # Make dirs | 97 | # Make dirs |
202 | 74 | install -d $(DESTDIR)$(LIBDIR) | 98 | install -d $(DEST_LIBDIR) |
203 | 75 | install -d $(DESTDIR)$(PAMDIR) | 99 | install -d $(DEST_PAMDIR) |
204 | 76 | install -d $(DESTDIR)$(BINDIR) | 100 | install -d $(DEST_BINDIR) |
205 | 77 | install -d $(DESTDIR)$(MANDIR)/man8 | 101 | install -d $(DEST_MANDIR)/man8 |
206 | 78 | # NSS modules | 102 | # NSS modules |
210 | 79 | install -m 0644 -t $(DESTDIR)$(LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) | 103 | install -m 0644 -t $(DEST_LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) |
211 | 80 | ln -sf $(NSS_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_OSLOGIN_SONAME) | 104 | ln -sf $(NSS_OSLOGIN) $(DEST_LIBDIR)/$(NSS_OSLOGIN_SONAME) |
212 | 81 | ln -sf $(NSS_CACHE_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME) | 105 | ln -sf $(NSS_CACHE_OSLOGIN) $(DEST_LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME) |
213 | 82 | # PAM modules | 106 | # PAM modules |
215 | 83 | install -m 0644 -t $(DESTDIR)$(PAMDIR) $(PAM_LOGIN) | 107 | install -m 0644 -t $(DEST_PAMDIR) $(PAM_LOGIN) $(PAM_ADMIN) |
216 | 84 | # Binaries | 108 | # Binaries |
218 | 85 | install -m 0755 -t $(DESTDIR)$(BINDIR) $(BINARIES) | 109 | install -m 0755 -t $(DEST_BINDIR) $(BINARIES) |
219 | 86 | # Manpages | 110 | # Manpages |
225 | 87 | install -m 0644 -t $(DESTDIR)$(MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/nss-cache-oslogin.8 | 111 | install -m 0644 -t $(DEST_MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/nss-cache-oslogin.8 |
226 | 88 | gzip -9f $(DESTDIR)$(MANDIR)/man8/nss-oslogin.8 | 112 | gzip -9f $(DEST_MANDIR)/man8/nss-oslogin.8 |
227 | 89 | gzip -9f $(DESTDIR)$(MANDIR)/man8/nss-cache-oslogin.8 | 113 | gzip -9f $(DEST_MANDIR)/man8/nss-cache-oslogin.8 |
228 | 90 | ln -sf nss-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz | 114 | ln -sf nss-oslogin.8.gz $(DEST_MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz |
229 | 91 | ln -sf nss-cache-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz | 115 | ln -sf nss-cache-oslogin.8.gz $(DEST_MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz |
230 | 92 | ifdef INSTALL_SELINUX | 116 | ifdef INSTALL_SELINUX |
231 | 93 | # SELinux policy package | 117 | # SELinux policy package |
234 | 94 | install -d $(DESTDIR)/usr/share/selinux/packages | 118 | install -d $(DEST_SELINUX) |
235 | 95 | install -m 0644 -t $(DESTDIR)/usr/share/selinux/packages $(TOPDIR)/selinux/oslogin.pp | 119 | install -m 0644 -t $(DEST_SELINUX) $(TOPDIR)/selinux/oslogin.pp |
236 | 96 | endif | 120 | endif |
237 | 97 | ifdef INSTALL_CRON | 121 | ifdef INSTALL_CRON |
238 | 98 | # Cache refresh cron | 122 | # Cache refresh cron |
241 | 99 | install -d $(DESTDIR)$(CRONDIR) | 123 | install -d $(DEST_CRONDIR) |
242 | 100 | install -m 0644 $(TOPDIR)/cron.d $(DESTDIR)$(CRONDIR)/google-compute-engine-oslogin | 124 | install -m 0644 $(TOPDIR)/cron.d $(DEST_CRONDIR)/google-compute-engine-oslogin |
243 | 101 | else | 125 | else |
244 | 102 | # Cache refresh systemd timer | 126 | # Cache refresh systemd timer |
249 | 103 | install -d $(DESTDIR)$(SYSTEMDDIR) | 127 | install -d $(DEST_SYSTEMDDIR) |
250 | 104 | install -m 0644 -t $(DESTDIR)$(SYSTEMDDIR) $(TOPDIR)/google-oslogin-cache.timer $(TOPDIR)/google-oslogin-cache.service | 128 | install -m 0644 -t $(DEST_SYSTEMDDIR) $(TOPDIR)/google-oslogin-cache.timer $(TOPDIR)/google-oslogin-cache.service |
251 | 105 | install -d $(DESTDIR)$(PRESETDIR) | 129 | install -d $(DEST_PRESETDIR) |
252 | 106 | install -m 0644 -t $(DESTDIR)$(PRESETDIR) $(TOPDIR)/90-google-compute-engine-oslogin.preset | 130 | install -m 0644 -t $(DEST_PRESETDIR) $(TOPDIR)/90-google-compute-engine-oslogin.preset |
253 | 107 | endif | 131 | endif |
254 | diff --git a/src/include/oslogin_utils.h b/src/include/oslogin_utils.h | |||
255 | index 368790e..e7c41fe 100644 | |||
256 | --- a/src/include/oslogin_utils.h | |||
257 | +++ b/src/include/oslogin_utils.h | |||
258 | @@ -186,6 +186,9 @@ size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp); | |||
259 | 186 | bool HttpGet(const string& url, string* response, long* http_code); | 186 | bool HttpGet(const string& url, string* response, long* http_code); |
260 | 187 | bool HttpPost(const string& url, const string& data, string* response, | 187 | bool HttpPost(const string& url, const string& data, string* response, |
261 | 188 | long* http_code); | 188 | long* http_code); |
262 | 189 | // Based on known MDS status codes returns whether the HTTP request | ||
263 | 190 | // should be retried or not. | ||
264 | 191 | bool ShouldRetry(long http_code); | ||
265 | 189 | 192 | ||
266 | 190 | // Returns whether user_name is a valid OsLogin user name. | 193 | // Returns whether user_name is a valid OsLogin user name. |
267 | 191 | bool ValidateUserName(const string& user_name); | 194 | bool ValidateUserName(const string& user_name); |
268 | @@ -294,6 +297,11 @@ extern void SysLogErr(const char *fmt, ...); | |||
269 | 294 | 297 | ||
270 | 295 | // AuthoOptions wraps authorization options. | 298 | // AuthoOptions wraps authorization options. |
271 | 296 | struct AuthOptions { | 299 | struct AuthOptions { |
272 | 300 | // admin_policy_required determines if a user is only authorized if admin | ||
273 | 301 | // policy is available for such a user. i.e. AuthorizeUser() should return | ||
274 | 302 | // false if adminLogin is not available. | ||
275 | 303 | bool admin_policy_required; | ||
276 | 304 | |||
277 | 297 | // security_key determines if the MDS "/users?..." should use | 305 | // security_key determines if the MDS "/users?..." should use |
278 | 298 | // the view=securityKey parameter. | 306 | // the view=securityKey parameter. |
279 | 299 | bool security_key; | 307 | bool security_key; |
280 | diff --git a/src/oslogin_utils.cc b/src/oslogin_utils.cc | |||
281 | index f8bbf9c..aad560f 100644 | |||
282 | --- a/src/oslogin_utils.cc | |||
283 | +++ b/src/oslogin_utils.cc | |||
284 | @@ -12,7 +12,7 @@ | |||
285 | 12 | // See the License for the specific language governing permissions and | 12 | // See the License for the specific language governing permissions and |
286 | 13 | // limitations under the License. | 13 | // limitations under the License. |
287 | 14 | 14 | ||
289 | 15 | // Requires libcurl4-openssl-dev libjson0 and libjson0-dev | 15 | // Requires libcurl4-openssl-dev, libjson-c5, and libjson-c-dev |
290 | 16 | #include <curl/curl.h> | 16 | #include <curl/curl.h> |
291 | 17 | #include <errno.h> | 17 | #include <errno.h> |
292 | 18 | #include <grp.h> | 18 | #include <grp.h> |
293 | @@ -48,7 +48,10 @@ | |||
294 | 48 | using std::string; | 48 | using std::string; |
295 | 49 | 49 | ||
296 | 50 | // Maximum number of retries for HTTP requests. | 50 | // Maximum number of retries for HTTP requests. |
298 | 51 | const int kMaxRetries = 1; | 51 | const int kMaxRetries = 3; |
299 | 52 | |||
300 | 53 | // Backoff duration 1 sec between retries. | ||
301 | 54 | const int kBackoffDuration = 1; | ||
302 | 52 | 55 | ||
303 | 53 | // Regex for validating user names. | 56 | // Regex for validating user names. |
304 | 54 | static const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$"; | 57 | static const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$"; |
305 | @@ -189,11 +192,29 @@ bool NssCache::GetNextGroup(BufferManager* buf, struct group* result, int* errno | |||
306 | 189 | return ParseJsonToGroup(cached_passwd, result, buf, errnop); | 192 | return ParseJsonToGroup(cached_passwd, result, buf, errnop); |
307 | 190 | } | 193 | } |
308 | 191 | 194 | ||
309 | 195 | // ParseJsonRoot is declared early here, away from the other parsing functions | ||
310 | 196 | // found later (in the "JSON Parsing" section), so LoadJsonUsersToCache can | ||
311 | 197 | // take advantage of the improved error handling ParseJsonRoot offers. | ||
312 | 198 | json_object* ParseJsonRoot(const string& json) { | ||
313 | 199 | json_object* root = NULL; | ||
314 | 200 | struct json_tokener* tok = json_tokener_new(); | ||
315 | 201 | |||
316 | 202 | root = json_tokener_parse_ex(tok, json.c_str(), -1); | ||
317 | 203 | if (root == NULL) { | ||
318 | 204 | enum json_tokener_error jerr = json_tokener_get_error(tok); | ||
319 | 205 | string error_message = json_tokener_error_desc(jerr); | ||
320 | 206 | SysLogErr("Failed to parse root JSON element: \"%s\", from input \"%s\"", | ||
321 | 207 | error_message, json); | ||
322 | 208 | } | ||
323 | 209 | |||
324 | 210 | json_tokener_free(tok); | ||
325 | 211 | return root; | ||
326 | 212 | } | ||
327 | 213 | |||
328 | 192 | bool NssCache::LoadJsonUsersToCache(string response) { | 214 | bool NssCache::LoadJsonUsersToCache(string response) { |
329 | 193 | Reset(); | 215 | Reset(); |
330 | 194 | 216 | ||
333 | 195 | json_object* root = NULL; | 217 | json_object* root = ParseJsonRoot(response); |
332 | 196 | root = json_tokener_parse(response.c_str()); | ||
334 | 197 | if (root == NULL) { | 218 | if (root == NULL) { |
335 | 198 | return false; | 219 | return false; |
336 | 199 | } | 220 | } |
337 | @@ -392,6 +413,22 @@ size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp) { | |||
338 | 392 | return 0; | 413 | return 0; |
339 | 393 | } | 414 | } |
340 | 394 | 415 | ||
341 | 416 | bool ShouldRetry(long http_code) { | ||
342 | 417 | if (http_code == 200) { | ||
343 | 418 | // Request returned successfully, no need to retry. | ||
344 | 419 | return false; | ||
345 | 420 | } | ||
346 | 421 | if (http_code == 404) { | ||
347 | 422 | // Metadata key does not exist, no point of retrying. | ||
348 | 423 | return false; | ||
349 | 424 | } | ||
350 | 425 | if (http_code == 400) { | ||
351 | 426 | // Request parameters are bad, no point of retrying. | ||
352 | 427 | return false; | ||
353 | 428 | } | ||
354 | 429 | return true; | ||
355 | 430 | } | ||
356 | 431 | |||
357 | 395 | bool HttpDo(const string& url, const string& data, string* response, long* http_code) { | 432 | bool HttpDo(const string& url, const string& data, string* response, long* http_code) { |
358 | 396 | if (response == NULL || http_code == NULL) { | 433 | if (response == NULL || http_code == NULL) { |
359 | 397 | return false; | 434 | return false; |
360 | @@ -410,6 +447,10 @@ bool HttpDo(const string& url, const string& data, string* response, long* http_ | |||
361 | 410 | return false; | 447 | return false; |
362 | 411 | } | 448 | } |
363 | 412 | do { | 449 | do { |
364 | 450 | // Apply backoff strategy before retrying. | ||
365 | 451 | if (retry_count > 0) { | ||
366 | 452 | sleep(kBackoffDuration); | ||
367 | 453 | } | ||
368 | 413 | response_stream.str(""); | 454 | response_stream.str(""); |
369 | 414 | response_stream.clear(); | 455 | response_stream.clear(); |
370 | 415 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); | 456 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); |
371 | @@ -428,7 +469,7 @@ bool HttpDo(const string& url, const string& data, string* response, long* http_ | |||
372 | 428 | return false; | 469 | return false; |
373 | 429 | } | 470 | } |
374 | 430 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code); | 471 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code); |
376 | 431 | } while (retry_count++ < kMaxRetries && *http_code == 500); | 472 | } while (retry_count++ < kMaxRetries && ShouldRetry(*http_code)); |
377 | 432 | curl_slist_free_all(header_list); | 473 | curl_slist_free_all(header_list); |
378 | 433 | } | 474 | } |
379 | 434 | *response = response_stream.str(); | 475 | *response = response_stream.str(); |
380 | @@ -506,14 +547,12 @@ bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop) { | |||
381 | 506 | // ----------------- JSON Parsing ----------------- | 547 | // ----------------- JSON Parsing ----------------- |
382 | 507 | 548 | ||
383 | 508 | bool ParseJsonToUsers(const string& json, std::vector<string>* result) { | 549 | bool ParseJsonToUsers(const string& json, std::vector<string>* result) { |
384 | 509 | json_object* root = NULL; | ||
385 | 510 | root = json_tokener_parse(json.c_str()); | ||
386 | 511 | if (root == NULL) { | ||
387 | 512 | return false; | ||
388 | 513 | } | ||
389 | 514 | |||
390 | 515 | bool ret = false; | 550 | bool ret = false; |
391 | 516 | 551 | ||
392 | 552 | json_object* root = ParseJsonRoot(json); | ||
393 | 553 | if (root == NULL) { | ||
394 | 554 | return ret; | ||
395 | 555 | } | ||
396 | 517 | json_object* users = NULL; | 556 | json_object* users = NULL; |
397 | 518 | if (!json_object_object_get_ex(root, "usernames", &users)) { | 557 | if (!json_object_object_get_ex(root, "usernames", &users)) { |
398 | 519 | ret = true; // means no users, not invalid. | 558 | ret = true; // means no users, not invalid. |
399 | @@ -535,19 +574,22 @@ cleanup: | |||
400 | 535 | } | 574 | } |
401 | 536 | 575 | ||
402 | 537 | bool ParseJsonToGroups(const string& json, std::vector<Group>* result) { | 576 | bool ParseJsonToGroups(const string& json, std::vector<Group>* result) { |
403 | 538 | json_object* root = NULL; | ||
404 | 539 | root = json_tokener_parse(json.c_str()); | ||
405 | 540 | if (root == NULL) { | ||
406 | 541 | return false; | ||
407 | 542 | } | ||
408 | 543 | |||
409 | 544 | bool ret = false; | 577 | bool ret = false; |
410 | 545 | 578 | ||
412 | 546 | json_object* groups = NULL; | 579 | json_object* root = ParseJsonRoot(json); |
413 | 580 | if (root == NULL) { | ||
414 | 581 | return ret; | ||
415 | 582 | } | ||
416 | 583 | json_object* groups; | ||
417 | 584 | json_type groupType; | ||
418 | 547 | if (!json_object_object_get_ex(root, "posixGroups", &groups)) { | 585 | if (!json_object_object_get_ex(root, "posixGroups", &groups)) { |
419 | 586 | SysLogErr("failed to parse POSIX groups from \"%s\"", json); | ||
420 | 548 | goto cleanup; | 587 | goto cleanup; |
421 | 549 | } | 588 | } |
423 | 550 | if (json_object_get_type(groups) != json_type_array) { | 589 | groupType = json_object_get_type(groups); |
424 | 590 | if (groupType != json_type_array) { | ||
425 | 591 | SysLogErr("parsed unexpected type for field \"posixGroups\"; " | ||
426 | 592 | "want a list, got %s", groupType); | ||
427 | 551 | goto cleanup; | 593 | goto cleanup; |
428 | 552 | } | 594 | } |
429 | 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++) { |
430 | @@ -555,11 +597,12 @@ bool ParseJsonToGroups(const string& json, std::vector<Group>* result) { | |||
431 | 555 | 597 | ||
432 | 556 | json_object* gid; | 598 | json_object* gid; |
433 | 557 | if (!json_object_object_get_ex(group, "gid", &gid)) { | 599 | if (!json_object_object_get_ex(group, "gid", &gid)) { |
434 | 600 | SysLogErr("failed to parse gid from group %s", json_object_get_string(group)); | ||
435 | 558 | goto cleanup; | 601 | goto cleanup; |
436 | 559 | } | 602 | } |
437 | 560 | |||
438 | 561 | json_object* name; | 603 | json_object* name; |
439 | 562 | if (!json_object_object_get_ex(group, "name", &name)) { | 604 | if (!json_object_object_get_ex(group, "name", &name)) { |
440 | 605 | SysLogErr("failed to parse name from group %s", json_object_get_string(group)); | ||
441 | 563 | goto cleanup; | 606 | goto cleanup; |
442 | 564 | } | 607 | } |
443 | 565 | 608 | ||
444 | @@ -589,22 +632,19 @@ cleanup: | |||
445 | 589 | 632 | ||
446 | 590 | bool ParseJsonToGroup(const string& json, struct group* result, BufferManager* | 633 | bool ParseJsonToGroup(const string& json, struct group* result, BufferManager* |
447 | 591 | buf, int* errnop) { | 634 | buf, int* errnop) { |
448 | 635 | bool ret = false; | ||
449 | 592 | *errnop = EINVAL; | 636 | *errnop = EINVAL; |
450 | 593 | int gr_gid = 65535; | 637 | int gr_gid = 65535; |
451 | 594 | 638 | ||
454 | 595 | json_object* group = NULL; | 639 | json_object* group = ParseJsonRoot(json); |
453 | 596 | group = json_tokener_parse(json.c_str()); | ||
455 | 597 | if (group == NULL) { | 640 | if (group == NULL) { |
456 | 598 | return false; | 641 | return false; |
457 | 599 | } | 642 | } |
458 | 600 | 643 | ||
459 | 601 | bool ret = false; | ||
460 | 602 | |||
461 | 603 | json_object* gid; | 644 | json_object* gid; |
462 | 604 | if (!json_object_object_get_ex(group, "gid", &gid)) { | 645 | if (!json_object_object_get_ex(group, "gid", &gid)) { |
463 | 605 | goto cleanup; | 646 | goto cleanup; |
464 | 606 | } | 647 | } |
465 | 607 | |||
466 | 608 | json_object* name; | 648 | json_object* name; |
467 | 609 | if (!json_object_object_get_ex(group, "name", &name)) { | 649 | if (!json_object_object_get_ex(group, "name", &name)) { |
468 | 610 | goto cleanup; | 650 | goto cleanup; |
469 | @@ -631,16 +671,13 @@ cleanup: | |||
470 | 631 | 671 | ||
471 | 632 | std::vector<string> ParseJsonToSshKeys(const string& json) { | 672 | std::vector<string> ParseJsonToSshKeys(const string& json) { |
472 | 633 | std::vector<string> result; | 673 | std::vector<string> result; |
477 | 634 | json_object* ssh_public_keys = NULL; | 674 | json_object* root = ParseJsonRoot(json); |
474 | 635 | |||
475 | 636 | json_object* root = NULL; | ||
476 | 637 | root = json_tokener_parse(json.c_str()); | ||
478 | 638 | if (root == NULL) { | 675 | if (root == NULL) { |
479 | 639 | return result; | 676 | return result; |
480 | 640 | } | 677 | } |
481 | 641 | 678 | ||
482 | 642 | // Locate the sshPublicKeys object. | 679 | // Locate the sshPublicKeys object. |
484 | 643 | json_object* login_profiles = NULL; | 680 | json_object* login_profiles; |
485 | 644 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { | 681 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { |
486 | 645 | goto cleanup; | 682 | goto cleanup; |
487 | 646 | } | 683 | } |
488 | @@ -649,6 +686,7 @@ std::vector<string> ParseJsonToSshKeys(const string& json) { | |||
489 | 649 | } | 686 | } |
490 | 650 | login_profiles = json_object_array_get_idx(login_profiles, 0); | 687 | login_profiles = json_object_array_get_idx(login_profiles, 0); |
491 | 651 | 688 | ||
492 | 689 | json_object* ssh_public_keys; | ||
493 | 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)) { |
494 | 653 | goto cleanup; | 691 | goto cleanup; |
495 | 654 | } | 692 | } |
496 | @@ -701,16 +739,14 @@ cleanup: | |||
497 | 701 | 739 | ||
498 | 702 | std::vector<string> ParseJsonToSshKeysSk(const string& json) { | 740 | std::vector<string> ParseJsonToSshKeysSk(const string& json) { |
499 | 703 | std::vector<string> result; | 741 | std::vector<string> result; |
500 | 704 | json_object* security_keys = NULL; | ||
501 | 705 | 742 | ||
504 | 706 | json_object* root = NULL; | 743 | json_object* root = ParseJsonRoot(json); |
503 | 707 | root = json_tokener_parse(json.c_str()); | ||
505 | 708 | if (root == NULL) { | 744 | if (root == NULL) { |
506 | 709 | return result; | 745 | return result; |
507 | 710 | } | 746 | } |
508 | 711 | 747 | ||
509 | 712 | // Locate the securityKeys array. | 748 | // Locate the securityKeys array. |
511 | 713 | json_object* login_profiles = NULL; | 749 | json_object* login_profiles; |
512 | 714 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { | 750 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { |
513 | 715 | goto cleanup; | 751 | goto cleanup; |
514 | 716 | } | 752 | } |
515 | @@ -720,9 +756,11 @@ std::vector<string> ParseJsonToSshKeysSk(const string& json) { | |||
516 | 720 | 756 | ||
517 | 721 | login_profiles = json_object_array_get_idx(login_profiles, 0); | 757 | login_profiles = json_object_array_get_idx(login_profiles, 0); |
518 | 722 | 758 | ||
519 | 759 | json_object* security_keys; | ||
520 | 723 | if (!json_object_object_get_ex(login_profiles, "securityKeys", &security_keys)) { | 760 | if (!json_object_object_get_ex(login_profiles, "securityKeys", &security_keys)) { |
521 | 724 | goto cleanup; | 761 | goto cleanup; |
522 | 725 | } | 762 | } |
523 | 763 | |||
524 | 726 | if (json_object_get_type(security_keys) != json_type_array) { | 764 | if (json_object_get_type(security_keys) != json_type_array) { |
525 | 727 | goto cleanup; | 765 | goto cleanup; |
526 | 728 | } | 766 | } |
527 | @@ -757,19 +795,18 @@ cleanup: | |||
528 | 757 | 795 | ||
529 | 758 | bool ParseJsonToPasswd(const string& json, struct passwd* result, BufferManager* | 796 | bool ParseJsonToPasswd(const string& json, struct passwd* result, BufferManager* |
530 | 759 | buf, int* errnop) { | 797 | buf, int* errnop) { |
531 | 798 | bool ret = false; | ||
532 | 760 | *errnop = EINVAL; | 799 | *errnop = EINVAL; |
533 | 761 | json_object* root = NULL; | 800 | json_object* root = NULL; |
534 | 762 | json_object* origroot = NULL; | 801 | json_object* origroot = NULL; |
535 | 763 | 802 | ||
537 | 764 | origroot = root = json_tokener_parse(json.c_str()); | 803 | origroot = root = ParseJsonRoot(json); |
538 | 765 | if (root == NULL) { | 804 | if (root == NULL) { |
539 | 766 | return false; | 805 | return false; |
540 | 767 | } | 806 | } |
541 | 768 | 807 | ||
546 | 769 | bool ret = false; | 808 | json_object* posix_accounts; |
547 | 770 | json_object* posix_accounts = NULL; | 809 | json_object* login_profiles; |
544 | 771 | |||
545 | 772 | json_object* login_profiles = NULL; | ||
548 | 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. |
549 | 774 | if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { | 811 | if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { |
550 | 775 | if (json_object_get_type(login_profiles) != json_type_array) { | 812 | if (json_object_get_type(login_profiles) != json_type_array) { |
551 | @@ -888,17 +925,16 @@ bool AddUsersToGroup(std::vector<string> users, struct group* result, | |||
552 | 888 | } | 925 | } |
553 | 889 | 926 | ||
554 | 890 | bool ParseJsonToEmail(const string& json, string* email) { | 927 | bool ParseJsonToEmail(const string& json, string* email) { |
557 | 891 | json_object* root = NULL; | 928 | bool ret = false; |
558 | 892 | root = json_tokener_parse(json.c_str()); | 929 | |
559 | 930 | json_object* root = ParseJsonRoot(json); | ||
560 | 893 | if (root == NULL) { | 931 | if (root == NULL) { |
562 | 894 | return false; | 932 | return ret; |
563 | 895 | } | 933 | } |
564 | 896 | 934 | ||
565 | 897 | bool ret = false; | ||
566 | 898 | json_object* json_email = NULL; | ||
567 | 899 | |||
568 | 900 | // Locate the email object. | 935 | // Locate the email object. |
570 | 901 | json_object* login_profiles = NULL; | 936 | json_object* login_profiles; |
571 | 937 | json_object* json_email; | ||
572 | 902 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { | 938 | if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) { |
573 | 903 | goto cleanup; | 939 | goto cleanup; |
574 | 904 | } | 940 | } |
575 | @@ -918,8 +954,7 @@ cleanup: | |||
576 | 918 | } | 954 | } |
577 | 919 | 955 | ||
578 | 920 | bool ParseJsonToSuccess(const string& json) { | 956 | bool ParseJsonToSuccess(const string& json) { |
581 | 921 | json_object* root = NULL; | 957 | json_object* root = ParseJsonRoot(json); |
580 | 922 | root = json_tokener_parse(json.c_str()); | ||
582 | 923 | if (root == NULL) { | 958 | if (root == NULL) { |
583 | 924 | return false; | 959 | return false; |
584 | 925 | } | 960 | } |
585 | @@ -934,17 +969,15 @@ bool ParseJsonToSuccess(const string& json) { | |||
586 | 934 | } | 969 | } |
587 | 935 | 970 | ||
588 | 936 | bool ParseJsonToKey(const string& json, const string& key, string* response) { | 971 | bool ParseJsonToKey(const string& json, const string& key, string* response) { |
591 | 937 | json_object* root = NULL; | 972 | bool ret = false; |
592 | 938 | root = json_tokener_parse(json.c_str()); | 973 | |
593 | 974 | json_object* root = ParseJsonRoot(json); | ||
594 | 939 | if (root == NULL) { | 975 | if (root == NULL) { |
596 | 940 | return false; | 976 | return ret; |
597 | 941 | } | 977 | } |
598 | 942 | 978 | ||
599 | 943 | bool ret = false; | ||
600 | 944 | json_object* json_response = NULL; | 979 | json_object* json_response = NULL; |
601 | 945 | const char* c_response = NULL; | 980 | const char* c_response = NULL; |
602 | 946 | |||
603 | 947 | |||
604 | 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)) { |
605 | 949 | goto cleanup; | 982 | goto cleanup; |
606 | 950 | } | 983 | } |
607 | @@ -962,13 +995,13 @@ cleanup: | |||
608 | 962 | } | 995 | } |
609 | 963 | 996 | ||
610 | 964 | bool ParseJsonToChallenges(const string& json, std::vector<Challenge>* challenges) { | 997 | bool ParseJsonToChallenges(const string& json, std::vector<Challenge>* challenges) { |
613 | 965 | json_object* root = NULL; | 998 | bool ret = false; |
614 | 966 | root = json_tokener_parse(json.c_str()); | 999 | |
615 | 1000 | json_object* root = ParseJsonRoot(json); | ||
616 | 967 | if (root == NULL) { | 1001 | if (root == NULL) { |
618 | 968 | return false; | 1002 | return ret; |
619 | 969 | } | 1003 | } |
620 | 970 | 1004 | ||
621 | 971 | bool ret = false; | ||
622 | 972 | json_object* challengeId = NULL; | 1005 | json_object* challengeId = NULL; |
623 | 973 | json_object* challengeType = NULL; | 1006 | json_object* challengeType = NULL; |
624 | 974 | json_object* challengeStatus = NULL; | 1007 | json_object* challengeStatus = NULL; |
625 | @@ -1260,18 +1293,18 @@ static bool ApplyPolicy(const char *user_name, string email, const char *policy, | |||
626 | 1260 | long http_code = 0; | 1293 | long http_code = 0; |
627 | 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. |
628 | 1262 | if (!HttpGet(url.str(), &response, &http_code)) { | 1295 | if (!HttpGet(url.str(), &response, &http_code)) { |
630 | 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); |
631 | 1264 | return false; | 1297 | return false; |
632 | 1265 | } | 1298 | } |
633 | 1266 | 1299 | ||
634 | 1267 | if (http_code != 200) { | 1300 | if (http_code != 200) { |
637 | 1268 | SysLogErr("Failed to validate organization user %s has login permission, " | 1301 | SysLogErr("Failed to validate that OS Login user %s has %s permission; " |
638 | 1269 | "got HTTP response code: %lu", user_name, http_code); | 1302 | "got HTTP response code: %lu", user_name, policy, http_code); |
639 | 1270 | return false; | 1303 | return false; |
640 | 1271 | } | 1304 | } |
641 | 1272 | 1305 | ||
642 | 1273 | if (!ParseJsonToSuccess(response)) { | 1306 | if (!ParseJsonToSuccess(response)) { |
644 | 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); |
645 | 1275 | return false; | 1308 | return false; |
646 | 1276 | } | 1309 | } |
647 | 1277 | 1310 | ||
648 | @@ -1369,6 +1402,9 @@ bool AuthorizeUser(const char *user_name, struct AuthOptions opts, string *user_ | |||
649 | 1369 | } | 1402 | } |
650 | 1370 | } else { | 1403 | } else { |
651 | 1371 | remove(sudoers_filename.c_str()); | 1404 | remove(sudoers_filename.c_str()); |
652 | 1405 | if (opts.admin_policy_required) { | ||
653 | 1406 | return false; | ||
654 | 1407 | } | ||
655 | 1372 | } | 1408 | } |
656 | 1373 | 1409 | ||
657 | 1374 | return true; | 1410 | return true; |
658 | diff --git a/src/pam/pam_oslogin_admin.cc b/src/pam/pam_oslogin_admin.cc | |||
659 | 1375 | new file mode 100644 | 1411 | new file mode 100644 |
660 | index 0000000..06bb10b | |||
661 | --- /dev/null | |||
662 | +++ b/src/pam/pam_oslogin_admin.cc | |||
663 | @@ -0,0 +1,53 @@ | |||
664 | 1 | // Copyright 2024 Google Inc. All Rights Reserved. | ||
665 | 2 | // | ||
666 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
667 | 4 | // you may not use this file except in compliance with the License. | ||
668 | 5 | // You may obtain a copy of the License at | ||
669 | 6 | // | ||
670 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
671 | 8 | // | ||
672 | 9 | // Unless required by applicable law or agreed to in writing, software | ||
673 | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
674 | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
675 | 12 | // See the License for the specific language governing permissions and | ||
676 | 13 | // limitations under the License. | ||
677 | 14 | |||
678 | 15 | #include <security/pam_modules.h> | ||
679 | 16 | |||
680 | 17 | #include <compat.h> | ||
681 | 18 | #include <oslogin_utils.h> | ||
682 | 19 | |||
683 | 20 | using std::string; | ||
684 | 21 | |||
685 | 22 | using oslogin_utils::AuthOptions; | ||
686 | 23 | |||
687 | 24 | extern "C" { | ||
688 | 25 | |||
689 | 26 | // pm_sm_acct_mgmt is the account management PAM implementation for admin users (or users | ||
690 | 27 | // with the proper loginAdmin policy). This account management module is intended for custom | ||
691 | 28 | // configuration handling only, where users need a way to in their stack configurations to | ||
692 | 29 | // differentiate a OS Login user. The Google Guest Agent will not manage the lifecycle of | ||
693 | 30 | // this module, it will not add this to the stack as part of the standard/default configuration | ||
694 | 31 | // set. | ||
695 | 32 | PAM_EXTERN int | ||
696 | 33 | pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) { | ||
697 | 34 | struct AuthOptions opts; | ||
698 | 35 | const char *user_name; | ||
699 | 36 | string user_response; | ||
700 | 37 | |||
701 | 38 | if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) { | ||
702 | 39 | PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user."); | ||
703 | 40 | return PAM_PERM_DENIED; | ||
704 | 41 | } | ||
705 | 42 | |||
706 | 43 | opts = { 0 }; | ||
707 | 44 | opts.admin_policy_required = true; | ||
708 | 45 | |||
709 | 46 | if (!AuthorizeUser(user_name, opts, &user_response)) { | ||
710 | 47 | return PAM_PERM_DENIED; | ||
711 | 48 | } | ||
712 | 49 | |||
713 | 50 | return PAM_SUCCESS; | ||
714 | 51 | } | ||
715 | 52 | |||
716 | 53 | } | ||
717 | diff --git a/src/pam/pam_oslogin_login.cc b/src/pam/pam_oslogin_login.cc | |||
718 | index ca41ed3..5d863d2 100644 | |||
719 | --- a/src/pam/pam_oslogin_login.cc | |||
720 | +++ b/src/pam/pam_oslogin_login.cc | |||
721 | @@ -22,6 +22,7 @@ | |||
722 | 22 | #include <compat.h> | 22 | #include <compat.h> |
723 | 23 | #include <oslogin_utils.h> | 23 | #include <oslogin_utils.h> |
724 | 24 | 24 | ||
725 | 25 | using oslogin_utils::AuthOptions; | ||
726 | 25 | using oslogin_utils::ContinueSession; | 26 | using oslogin_utils::ContinueSession; |
727 | 26 | using oslogin_utils::GetUser; | 27 | using oslogin_utils::GetUser; |
728 | 27 | using oslogin_utils::ParseJsonToChallenges; | 28 | using oslogin_utils::ParseJsonToChallenges; |
729 | @@ -32,6 +33,32 @@ using oslogin_utils::ValidateUserName; | |||
730 | 32 | 33 | ||
731 | 33 | extern "C" { | 34 | extern "C" { |
732 | 34 | 35 | ||
733 | 36 | // pm_sm_acct_mgmt is the account management PAM implementation for non-admin users (or users | ||
734 | 37 | // without the proper loginAdmin policy). This account management module is intended for custom | ||
735 | 38 | // configuration handling only, where users need a way to in their stack configurations to | ||
736 | 39 | // differentiate a OS Login user. The Google Guest Agent will not manage the lifecycle of | ||
737 | 40 | // this module, it will not add this to the stack as part of the standard/default configuration | ||
738 | 41 | // set. | ||
739 | 42 | PAM_EXTERN int | ||
740 | 43 | pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) { | ||
741 | 44 | struct AuthOptions opts; | ||
742 | 45 | const char *user_name; | ||
743 | 46 | string user_response; | ||
744 | 47 | |||
745 | 48 | if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) { | ||
746 | 49 | PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user."); | ||
747 | 50 | return PAM_PERM_DENIED; | ||
748 | 51 | } | ||
749 | 52 | |||
750 | 53 | opts = { 0 }; | ||
751 | 54 | |||
752 | 55 | if (!AuthorizeUser(user_name, opts, &user_response)) { | ||
753 | 56 | return PAM_PERM_DENIED; | ||
754 | 57 | } | ||
755 | 58 | |||
756 | 59 | return PAM_SUCCESS; | ||
757 | 60 | } | ||
758 | 61 | |||
759 | 35 | PAM_EXTERN int | 62 | PAM_EXTERN int |
760 | 36 | pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv) { | 63 | pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv) { |
761 | 37 | return PAM_SUCCESS; | 64 | return PAM_SUCCESS; |
762 | diff --git a/test/oslogin_utils_test.cc b/test/oslogin_utils_test.cc | |||
763 | index 3451f61..0646a34 100644 | |||
764 | --- a/test/oslogin_utils_test.cc | |||
765 | +++ b/test/oslogin_utils_test.cc | |||
766 | @@ -460,6 +460,13 @@ TEST(GetGroupByTest, GetGroupByGIDSucceeds) { | |||
767 | 460 | ASSERT_EQ(errnop, 0); | 460 | ASSERT_EQ(errnop, 0); |
768 | 461 | } | 461 | } |
769 | 462 | 462 | ||
770 | 463 | TEST(CurlClient, RetryLogic) { | ||
771 | 464 | ASSERT_FALSE(ShouldRetry(200)); | ||
772 | 465 | ASSERT_FALSE(ShouldRetry(404)); | ||
773 | 466 | ASSERT_FALSE(ShouldRetry(400)); | ||
774 | 467 | ASSERT_TRUE(ShouldRetry(429)); | ||
775 | 468 | } | ||
776 | 469 | |||
777 | 463 | TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) { | 470 | TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) { |
778 | 464 | string test_user = | 471 | string test_user = |
779 | 465 | "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" | 472 | "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":[" |
Thank you, this was straightforward!
Sponsored:
$ dput ubuntu ../google- compute- engine- oslogin_ 20240701. 00-0ubuntu1\ ~22.04. 0_source. changes compute- engine- oslogin using ftp to ubuntu (host: upload.ubuntu.com; directory: /ubuntu) distribution: check whether the target distribution is currently supported (using distro-info) compute- engine- oslogin_ 20240701. 00-0ubuntu1~ 22.04.0. dsc compute- engine- oslogin_ 20240701. 00.orig. tar.gz compute- engine- oslogin_ 20240701. 00-0ubuntu1~ 22.04.0. debian. tar.xz compute- engine- oslogin_ 20240701. 00-0ubuntu1~ 22.04.0_ source. buildinfo compute- engine- oslogin_ 20240701. 00-0ubuntu1~ 22.04.0_ source. changes
Uploading google-
running supported-
{'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-
Uploading google-
Uploading google-
Uploading google-
Uploading google-