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