Gentoo Archives: gentoo-commits

From: Jory Pratt <anarchy@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/musl:master commit in: sys-auth/polkit/files/, sys-auth/polkit/
Date: Thu, 11 Feb 2021 17:32:10
Message-Id: 1613062567.77abc7da6c7baad08c1c99ea3a04893e891023a1.anarchy@gentoo
1 commit: 77abc7da6c7baad08c1c99ea3a04893e891023a1
2 Author: Vjaceslavs Klimovs <vklimovs <AT> gmail <DOT> com>
3 AuthorDate: Mon Feb 8 01:36:27 2021 +0000
4 Commit: Jory Pratt <anarchy <AT> gentoo <DOT> org>
5 CommitDate: Thu Feb 11 16:56:07 2021 +0000
6 URL: https://gitweb.gentoo.org/proj/musl.git/commit/?id=77abc7da
7
8 sys-auth/polkit: add polkit-0.118-r1 w/o spidermonkey dep and optional netgroup
9
10 Signed-off-by: Vjaceslavs Klimovs <vklimovs <AT> gmail.com>
11 Signed-off-by: Jory Pratt <anarchy <AT> gentoo.org>
12
13 sys-auth/polkit/files/polkit-0.118-duktape.patch | 1499 ++++++++++++++++++++
14 sys-auth/polkit/files/polkit-0.118-elogind.patch | 28 +
15 ...lkit-0.118-make-netgroup-support-optional.patch | 219 +++
16 sys-auth/polkit/polkit-0.118-r1.ebuild | 134 ++
17 4 files changed, 1880 insertions(+)
18
19 diff --git a/sys-auth/polkit/files/polkit-0.118-duktape.patch b/sys-auth/polkit/files/polkit-0.118-duktape.patch
20 new file mode 100644
21 index 0000000..f3f69e3
22 --- /dev/null
23 +++ b/sys-auth/polkit/files/polkit-0.118-duktape.patch
24 @@ -0,0 +1,1499 @@
25 +diff --git a/configure.ac b/configure.ac
26 +index 5cedb4eca980f050fb5855ab577e93100adf8fec..6c274869f39d4b65b08f7cdb9e461b5182d297ec 100644
27 +--- a/configure.ac
28 ++++ b/configure.ac
29 +@@ -79,11 +79,22 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0])
30 + AC_SUBST(GLIB_CFLAGS)
31 + AC_SUBST(GLIB_LIBS)
32 +
33 +-PKG_CHECK_MODULES(LIBJS, [mozjs-78])
34 +-
35 +-AC_SUBST(LIBJS_CFLAGS)
36 +-AC_SUBST(LIBJS_CXXFLAGS)
37 +-AC_SUBST(LIBJS_LIBS)
38 ++dnl ---------------------------------------------------------------------------
39 ++dnl - Check javascript backend
40 ++dnl ---------------------------------------------------------------------------
41 ++AC_ARG_WITH(duktape, AS_HELP_STRING([--with-duktape],[Use Duktape as javascript backend]),with_duktape=yes,with_duktape=no)
42 ++AS_IF([test x${with_duktape} == xyes], [
43 ++ PKG_CHECK_MODULES(LIBJS, [duktape >= 2.0.0 ])
44 ++ AC_SUBST(LIBJS_CFLAGS)
45 ++ AC_SUBST(LIBJS_LIBS)
46 ++], [
47 ++ PKG_CHECK_MODULES(LIBJS, [mozjs-78])
48 ++
49 ++ AC_SUBST(LIBJS_CFLAGS)
50 ++ AC_SUBST(LIBJS_CXXFLAGS)
51 ++ AC_SUBST(LIBJS_LIBS)
52 ++])
53 ++AM_CONDITIONAL(USE_DUKTAPE, [test x$with_duktape == xyes], [Using duktape as javascript engine library])
54 +
55 + EXPAT_LIB=""
56 + AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here],
57 +@@ -580,6 +591,13 @@ echo "
58 + PAM support: ${have_pam}
59 + systemdsystemunitdir: ${systemdsystemunitdir}
60 + polkitd user: ${POLKITD_USER}"
61 ++if test "x${with_duktape}" = xyes; then
62 ++echo "
63 ++ Javascript engine: Duktape"
64 ++else
65 ++echo "
66 ++ Javascript engine: Mozjs"
67 ++fi
68 +
69 + if test "$have_pam" = yes ; then
70 + echo "
71 +diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
72 +index e48b739cc0a4e7606be0271ba4b4e3bd33b08545..9572b067effdf6f0dcd1c6b17b2e8c59c1ed6238 100644
73 +--- a/src/polkitbackend/Makefile.am
74 ++++ b/src/polkitbackend/Makefile.am
75 +@@ -33,7 +33,7 @@ libpolkit_backend_1_la_SOURCES = \
76 + polkitbackendprivate.h \
77 + polkitbackendauthority.h polkitbackendauthority.c \
78 + polkitbackendinteractiveauthority.h polkitbackendinteractiveauthority.c \
79 +- polkitbackendjsauthority.h polkitbackendjsauthority.cpp \
80 ++ polkitbackendjsauthority.h \
81 + polkitbackendactionpool.h polkitbackendactionpool.c \
82 + polkitbackendactionlookup.h polkitbackendactionlookup.c \
83 + $(NULL)
84 +@@ -51,19 +51,27 @@ libpolkit_backend_1_la_CFLAGS = \
85 + -D_POLKIT_BACKEND_COMPILATION \
86 + $(GLIB_CFLAGS) \
87 + $(LIBSYSTEMD_CFLAGS) \
88 +- $(LIBJS_CFLAGS) \
89 ++ $(LIBJS_CFLAGS) \
90 + $(NULL)
91 +
92 + libpolkit_backend_1_la_CXXFLAGS = $(libpolkit_backend_1_la_CFLAGS)
93 +
94 + libpolkit_backend_1_la_LIBADD = \
95 + $(GLIB_LIBS) \
96 ++ $(DUKTAPE_LIBS) \
97 + $(LIBSYSTEMD_LIBS) \
98 + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \
99 + $(EXPAT_LIBS) \
100 +- $(LIBJS_LIBS) \
101 ++ $(LIBJS_LIBS) \
102 + $(NULL)
103 +
104 ++if USE_DUKTAPE
105 ++libpolkit_backend_1_la_SOURCES += polkitbackendduktapeauthority.c
106 ++libpolkit_backend_1_la_LIBADD += -lm
107 ++else
108 ++libpolkit_backend_1_la_SOURCES += polkitbackendjsauthority.cpp
109 ++endif
110 ++
111 + rulesdir = $(sysconfdir)/polkit-1/rules.d
112 + rules_DATA = 50-default.rules
113 +
114 +diff --git a/src/polkitbackend/polkitbackendduktapeauthority.c b/src/polkitbackend/polkitbackendduktapeauthority.c
115 +new file mode 100644
116 +index 0000000000000000000000000000000000000000..ae984535ed88003ab1b0965e3e109a848479c047
117 +--- /dev/null
118 ++++ b/src/polkitbackend/polkitbackendduktapeauthority.c
119 +@@ -0,0 +1,1404 @@
120 ++/*
121 ++ * Copyright (C) 2008-2012 Red Hat, Inc.
122 ++ * Copyright (C) 2015 Tangent Space <jstpierre@×××××××.net>
123 ++ * Copyright (C) 2019 Wu Xiaotian <yetist@×××××.com>
124 ++ *
125 ++ * This library is free software; you can redistribute it and/or
126 ++ * modify it under the terms of the GNU Lesser General Public
127 ++ * License as published by the Free Software Foundation; either
128 ++ * version 2 of the License, or (at your option) any later version.
129 ++ *
130 ++ * This library is distributed in the hope that it will be useful,
131 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
132 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
133 ++ * Lesser General Public License for more details.
134 ++ *
135 ++ * You should have received a copy of the GNU Lesser General
136 ++ * Public License along with this library; if not, write to the
137 ++ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
138 ++ * Boston, MA 02111-1307, USA.
139 ++ *
140 ++ * Author: David Zeuthen <davidz@××××××.com>
141 ++ */
142 ++
143 ++#include "config.h"
144 ++#include <sys/wait.h>
145 ++#include <errno.h>
146 ++#include <pwd.h>
147 ++#include <grp.h>
148 ++#include <netdb.h>
149 ++#include <string.h>
150 ++#include <glib/gstdio.h>
151 ++#include <locale.h>
152 ++#include <glib/gi18n-lib.h>
153 ++
154 ++#include <polkit/polkit.h>
155 ++#include "polkitbackendjsauthority.h"
156 ++
157 ++#include <polkit/polkitprivate.h>
158 ++
159 ++#ifdef HAVE_LIBSYSTEMD
160 ++#include <systemd/sd-login.h>
161 ++#endif /* HAVE_LIBSYSTEMD */
162 ++
163 ++#include "initjs.h" /* init.js */
164 ++#include "duktape.h"
165 ++
166 ++/**
167 ++ * SECTION:polkitbackendjsauthority
168 ++ * @title: PolkitBackendJsAuthority
169 ++ * @short_description: JS Authority
170 ++ * @stability: Unstable
171 ++ *
172 ++ * An implementation of #PolkitBackendAuthority that reads and
173 ++ * evalates Javascript files and supports interaction with
174 ++ * authentication agents (virtue of being based on
175 ++ * #PolkitBackendInteractiveAuthority).
176 ++ */
177 ++
178 ++/* ---------------------------------------------------------------------------------------------------- */
179 ++
180 ++struct _PolkitBackendJsAuthorityPrivate
181 ++{
182 ++ gchar **rules_dirs;
183 ++ GFileMonitor **dir_monitors; /* NULL-terminated array of GFileMonitor instances */
184 ++ duk_context *cx;
185 ++};
186 ++
187 ++#define WATCHDOG_TIMEOUT (15 * G_TIME_SPAN_SECOND)
188 ++
189 ++static void utils_spawn (const gchar *const *argv,
190 ++ guint timeout_seconds,
191 ++ GCancellable *cancellable,
192 ++ GAsyncReadyCallback callback,
193 ++ gpointer user_data);
194 ++
195 ++gboolean utils_spawn_finish (GAsyncResult *res,
196 ++ gint *out_exit_status,
197 ++ gchar **out_standard_output,
198 ++ gchar **out_standard_error,
199 ++ GError **error);
200 ++
201 ++static void on_dir_monitor_changed (GFileMonitor *monitor,
202 ++ GFile *file,
203 ++ GFile *other_file,
204 ++ GFileMonitorEvent event_type,
205 ++ gpointer user_data);
206 ++
207 ++/* ---------------------------------------------------------------------------------------------------- */
208 ++
209 ++enum
210 ++{
211 ++ PROP_0,
212 ++ PROP_RULES_DIRS,
213 ++};
214 ++
215 ++/* ---------------------------------------------------------------------------------------------------- */
216 ++
217 ++static GList *polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
218 ++ PolkitSubject *caller,
219 ++ PolkitSubject *subject,
220 ++ PolkitIdentity *user_for_subject,
221 ++ gboolean subject_is_local,
222 ++ gboolean subject_is_active,
223 ++ const gchar *action_id,
224 ++ PolkitDetails *details);
225 ++
226 ++static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorization_sync (
227 ++ PolkitBackendInteractiveAuthority *authority,
228 ++ PolkitSubject *caller,
229 ++ PolkitSubject *subject,
230 ++ PolkitIdentity *user_for_subject,
231 ++ gboolean subject_is_local,
232 ++ gboolean subject_is_active,
233 ++ const gchar *action_id,
234 ++ PolkitDetails *details,
235 ++ PolkitImplicitAuthorization implicit);
236 ++
237 ++G_DEFINE_TYPE (PolkitBackendJsAuthority, polkit_backend_js_authority, POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY);
238 ++
239 ++/* ---------------------------------------------------------------------------------------------------- */
240 ++
241 ++/* ---------------------------------------------------------------------------------------------------- */
242 ++
243 ++static void
244 ++polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
245 ++{
246 ++ authority->priv = G_TYPE_INSTANCE_GET_PRIVATE (authority,
247 ++ POLKIT_BACKEND_TYPE_JS_AUTHORITY,
248 ++ PolkitBackendJsAuthorityPrivate);
249 ++}
250 ++
251 ++static gint
252 ++rules_file_name_cmp (const gchar *a,
253 ++ const gchar *b)
254 ++{
255 ++ gint ret;
256 ++ const gchar *a_base;
257 ++ const gchar *b_base;
258 ++
259 ++ a_base = strrchr (a, '/');
260 ++ b_base = strrchr (b, '/');
261 ++
262 ++ g_assert (a_base != NULL);
263 ++ g_assert (b_base != NULL);
264 ++ a_base += 1;
265 ++ b_base += 1;
266 ++
267 ++ ret = g_strcmp0 (a_base, b_base);
268 ++ if (ret == 0)
269 ++ {
270 ++ /* /etc wins over /usr */
271 ++ ret = g_strcmp0 (a, b);
272 ++ g_assert (ret != 0);
273 ++ }
274 ++
275 ++ return ret;
276 ++}
277 ++
278 ++static void
279 ++load_scripts (PolkitBackendJsAuthority *authority)
280 ++{
281 ++ duk_context *cx = authority->priv->cx;
282 ++ GList *files = NULL;
283 ++ GList *l;
284 ++ guint num_scripts = 0;
285 ++ GError *error = NULL;
286 ++ guint n;
287 ++
288 ++ files = NULL;
289 ++
290 ++ for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
291 ++ {
292 ++ const gchar *dir_name = authority->priv->rules_dirs[n];
293 ++ GDir *dir = NULL;
294 ++
295 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
296 ++ "Loading rules from directory %s",
297 ++ dir_name);
298 ++
299 ++ dir = g_dir_open (dir_name,
300 ++ 0,
301 ++ &error);
302 ++ if (dir == NULL)
303 ++ {
304 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
305 ++ "Error opening rules directory: %s (%s, %d)",
306 ++ error->message, g_quark_to_string (error->domain), error->code);
307 ++ g_clear_error (&error);
308 ++ }
309 ++ else
310 ++ {
311 ++ const gchar *name;
312 ++ while ((name = g_dir_read_name (dir)) != NULL)
313 ++ {
314 ++ if (g_str_has_suffix (name, ".rules"))
315 ++ files = g_list_prepend (files, g_strdup_printf ("%s/%s", dir_name, name));
316 ++ }
317 ++ g_dir_close (dir);
318 ++ }
319 ++ }
320 ++
321 ++ files = g_list_sort (files, (GCompareFunc) rules_file_name_cmp);
322 ++
323 ++ for (l = files; l != NULL; l = l->next)
324 ++ {
325 ++ const gchar *filename = l->data;
326 ++
327 ++#if (DUK_VERSION >= 20000)
328 ++ gchar *contents;
329 ++ gsize length;
330 ++ GError *error = NULL;
331 ++ if (!g_file_get_contents (filename, &contents, &length, &error)){
332 ++ g_warning("Error when file contents of %s: %s\n", filename, error->message);
333 ++ g_error_free (error);
334 ++ continue;
335 ++ }
336 ++ if (duk_peval_lstring_noresult(cx, contents,length) != 0)
337 ++#else
338 ++ if (duk_peval_file_noresult (cx, filename) != 0)
339 ++#endif
340 ++ {
341 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
342 ++ "Error compiling script %s: %s",
343 ++ filename, duk_safe_to_string (authority->priv->cx, -1));
344 ++#if (DUK_VERSION >= 20000)
345 ++ g_free (contents);
346 ++#endif
347 ++ continue;
348 ++ }
349 ++#if (DUK_VERSION >= 20000)
350 ++ g_free (contents);
351 ++#endif
352 ++ num_scripts++;
353 ++ }
354 ++
355 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
356 ++ "Finished loading, compiling and executing %d rules",
357 ++ num_scripts);
358 ++ g_list_free_full (files, g_free);
359 ++}
360 ++
361 ++static void
362 ++reload_scripts (PolkitBackendJsAuthority *authority)
363 ++{
364 ++ duk_context *cx = authority->priv->cx;
365 ++
366 ++ duk_set_top (cx, 0);
367 ++ duk_get_global_string (cx, "polkit");
368 ++ duk_push_string (cx, "_deleteRules");
369 ++
370 ++ duk_call_prop (cx, 0, 0);
371 ++
372 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
373 ++ "Collecting garbage unconditionally...");
374 ++
375 ++ load_scripts (authority);
376 ++
377 ++ /* Let applications know we have new rules... */
378 ++ g_signal_emit_by_name (authority, "changed");
379 ++}
380 ++
381 ++static void
382 ++on_dir_monitor_changed (GFileMonitor *monitor,
383 ++ GFile *file,
384 ++ GFile *other_file,
385 ++ GFileMonitorEvent event_type,
386 ++ gpointer user_data)
387 ++{
388 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
389 ++
390 ++ /* TODO: maybe rate-limit so storms of events are collapsed into one with a 500ms resolution?
391 ++ * Because when editing a file with emacs we get 4-8 events..
392 ++ */
393 ++
394 ++ if (file != NULL)
395 ++ {
396 ++ gchar *name;
397 ++
398 ++ name = g_file_get_basename (file);
399 ++
400 ++ /* g_print ("event_type=%d file=%p name=%s\n", event_type, file, name); */
401 ++ if (!g_str_has_prefix (name, ".") &&
402 ++ !g_str_has_prefix (name, "#") &&
403 ++ g_str_has_suffix (name, ".rules") &&
404 ++ (event_type == G_FILE_MONITOR_EVENT_CREATED ||
405 ++ event_type == G_FILE_MONITOR_EVENT_DELETED ||
406 ++ event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
407 ++ {
408 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
409 ++ "Reloading rules");
410 ++ reload_scripts (authority);
411 ++ }
412 ++ g_free (name);
413 ++ }
414 ++}
415 ++
416 ++
417 ++static void
418 ++setup_file_monitors (PolkitBackendJsAuthority *authority)
419 ++{
420 ++ guint n;
421 ++ GPtrArray *p;
422 ++
423 ++ p = g_ptr_array_new ();
424 ++ for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
425 ++ {
426 ++ GFile *file;
427 ++ GError *error;
428 ++ GFileMonitor *monitor;
429 ++
430 ++ file = g_file_new_for_path (authority->priv->rules_dirs[n]);
431 ++ error = NULL;
432 ++ monitor = g_file_monitor_directory (file,
433 ++ G_FILE_MONITOR_NONE,
434 ++ NULL,
435 ++ &error);
436 ++ g_object_unref (file);
437 ++ if (monitor == NULL)
438 ++ {
439 ++ g_warning ("Error monitoring directory %s: %s",
440 ++ authority->priv->rules_dirs[n],
441 ++ error->message);
442 ++ g_clear_error (&error);
443 ++ }
444 ++ else
445 ++ {
446 ++ g_signal_connect (monitor,
447 ++ "changed",
448 ++ G_CALLBACK (on_dir_monitor_changed),
449 ++ authority);
450 ++ g_ptr_array_add (p, monitor);
451 ++ }
452 ++ }
453 ++ g_ptr_array_add (p, NULL);
454 ++ authority->priv->dir_monitors = (GFileMonitor**) g_ptr_array_free (p, FALSE);
455 ++}
456 ++
457 ++static duk_ret_t js_polkit_log (duk_context *cx);
458 ++static duk_ret_t js_polkit_spawn (duk_context *cx);
459 ++static duk_ret_t js_polkit_user_is_in_netgroup (duk_context *cx);
460 ++
461 ++static const duk_function_list_entry js_polkit_functions[] =
462 ++{
463 ++ { "log", js_polkit_log, 1 },
464 ++ { "spawn", js_polkit_spawn, 1 },
465 ++ { "_userIsInNetGroup", js_polkit_user_is_in_netgroup, 2 },
466 ++ { NULL, NULL, 0 },
467 ++};
468 ++
469 ++static void
470 ++polkit_backend_js_authority_constructed (GObject *object)
471 ++{
472 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
473 ++ duk_context *cx;
474 ++
475 ++ cx = duk_create_heap (NULL, NULL, NULL, authority, NULL);
476 ++ if (cx == NULL)
477 ++ goto fail;
478 ++
479 ++ authority->priv->cx = cx;
480 ++
481 ++ duk_push_global_object (cx);
482 ++ duk_push_object (cx);
483 ++ duk_put_function_list (cx, -1, js_polkit_functions);
484 ++ duk_put_prop_string (cx, -2, "polkit");
485 ++
486 ++ duk_eval_string (cx, init_js);
487 ++
488 ++ if (authority->priv->rules_dirs == NULL)
489 ++ {
490 ++ authority->priv->rules_dirs = g_new0 (gchar *, 3);
491 ++ authority->priv->rules_dirs[0] = g_strdup (PACKAGE_SYSCONF_DIR "/polkit-1/rules.d");
492 ++ authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
493 ++ }
494 ++
495 ++ setup_file_monitors (authority);
496 ++ load_scripts (authority);
497 ++
498 ++ G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
499 ++ return;
500 ++
501 ++ fail:
502 ++ g_critical ("Error initializing JavaScript environment");
503 ++ g_assert_not_reached ();
504 ++}
505 ++
506 ++static void
507 ++polkit_backend_js_authority_finalize (GObject *object)
508 ++{
509 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
510 ++ guint n;
511 ++
512 ++ for (n = 0; authority->priv->dir_monitors != NULL && authority->priv->dir_monitors[n] != NULL; n++)
513 ++ {
514 ++ GFileMonitor *monitor = authority->priv->dir_monitors[n];
515 ++ g_signal_handlers_disconnect_by_func (monitor,
516 ++ G_CALLBACK (on_dir_monitor_changed),
517 ++ authority);
518 ++ g_object_unref (monitor);
519 ++ }
520 ++ g_free (authority->priv->dir_monitors);
521 ++ g_strfreev (authority->priv->rules_dirs);
522 ++
523 ++ duk_destroy_heap (authority->priv->cx);
524 ++
525 ++ G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->finalize (object);
526 ++}
527 ++
528 ++static void
529 ++polkit_backend_js_authority_set_property (GObject *object,
530 ++ guint property_id,
531 ++ const GValue *value,
532 ++ GParamSpec *pspec)
533 ++{
534 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
535 ++
536 ++ switch (property_id)
537 ++ {
538 ++ case PROP_RULES_DIRS:
539 ++ g_assert (authority->priv->rules_dirs == NULL);
540 ++ authority->priv->rules_dirs = (gchar **) g_value_dup_boxed (value);
541 ++ break;
542 ++
543 ++ default:
544 ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
545 ++ break;
546 ++ }
547 ++}
548 ++
549 ++static const gchar *
550 ++polkit_backend_js_authority_get_name (PolkitBackendAuthority *authority)
551 ++{
552 ++ return "js";
553 ++}
554 ++
555 ++static const gchar *
556 ++polkit_backend_js_authority_get_version (PolkitBackendAuthority *authority)
557 ++{
558 ++ return PACKAGE_VERSION;
559 ++}
560 ++
561 ++static PolkitAuthorityFeatures
562 ++polkit_backend_js_authority_get_features (PolkitBackendAuthority *authority)
563 ++{
564 ++ return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
565 ++}
566 ++
567 ++static void
568 ++polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
569 ++{
570 ++ GObjectClass *gobject_class;
571 ++ PolkitBackendAuthorityClass *authority_class;
572 ++ PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
573 ++
574 ++
575 ++ gobject_class = G_OBJECT_CLASS (klass);
576 ++ gobject_class->finalize = polkit_backend_js_authority_finalize;
577 ++ gobject_class->set_property = polkit_backend_js_authority_set_property;
578 ++ gobject_class->constructed = polkit_backend_js_authority_constructed;
579 ++
580 ++ authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
581 ++ authority_class->get_name = polkit_backend_js_authority_get_name;
582 ++ authority_class->get_version = polkit_backend_js_authority_get_version;
583 ++ authority_class->get_features = polkit_backend_js_authority_get_features;
584 ++
585 ++ interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
586 ++ interactive_authority_class->get_admin_identities = polkit_backend_js_authority_get_admin_auth_identities;
587 ++ interactive_authority_class->check_authorization_sync = polkit_backend_js_authority_check_authorization_sync;
588 ++
589 ++ g_object_class_install_property (gobject_class,
590 ++ PROP_RULES_DIRS,
591 ++ g_param_spec_boxed ("rules-dirs",
592 ++ NULL,
593 ++ NULL,
594 ++ G_TYPE_STRV,
595 ++ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
596 ++
597 ++
598 ++ g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
599 ++}
600 ++
601 ++/* ---------------------------------------------------------------------------------------------------- */
602 ++
603 ++static void
604 ++set_property_str (duk_context *cx,
605 ++ const gchar *name,
606 ++ const gchar *value)
607 ++{
608 ++ duk_push_string (cx, value);
609 ++ duk_put_prop_string (cx, -2, name);
610 ++}
611 ++
612 ++static void
613 ++set_property_strv (duk_context *cx,
614 ++ const gchar *name,
615 ++ GPtrArray *value)
616 ++{
617 ++ guint n;
618 ++ duk_push_array (cx);
619 ++ for (n = 0; n < value->len; n++)
620 ++ {
621 ++ duk_push_string (cx, g_ptr_array_index (value, n));
622 ++ duk_put_prop_index (cx, -2, n);
623 ++ }
624 ++ duk_put_prop_string (cx, -2, name);
625 ++}
626 ++
627 ++static void
628 ++set_property_int32 (duk_context *cx,
629 ++ const gchar *name,
630 ++ gint32 value)
631 ++{
632 ++ duk_push_int (cx, value);
633 ++ duk_put_prop_string (cx, -2, name);
634 ++}
635 ++
636 ++static void
637 ++set_property_bool (duk_context *cx,
638 ++ const char *name,
639 ++ gboolean value)
640 ++{
641 ++ duk_push_boolean (cx, value);
642 ++ duk_put_prop_string (cx, -2, name);
643 ++}
644 ++
645 ++/* ---------------------------------------------------------------------------------------------------- */
646 ++
647 ++static gboolean
648 ++push_subject (duk_context *cx,
649 ++ PolkitSubject *subject,
650 ++ PolkitIdentity *user_for_subject,
651 ++ gboolean subject_is_local,
652 ++ gboolean subject_is_active,
653 ++ GError **error)
654 ++{
655 ++ gboolean ret = FALSE;
656 ++ pid_t pid;
657 ++ uid_t uid;
658 ++ gchar *user_name = NULL;
659 ++ GPtrArray *groups = NULL;
660 ++ struct passwd *passwd;
661 ++ char *seat_str = NULL;
662 ++ char *session_str = NULL;
663 ++
664 ++ duk_get_global_string (cx, "Subject");
665 ++ duk_new (cx, 0);
666 ++
667 ++ if (POLKIT_IS_UNIX_PROCESS (subject))
668 ++ {
669 ++ pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
670 ++ }
671 ++ else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
672 ++ {
673 ++ PolkitSubject *process;
674 ++ process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject), NULL, error);
675 ++ if (process == NULL)
676 ++ goto out;
677 ++ pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (process));
678 ++ g_object_unref (process);
679 ++ }
680 ++ else
681 ++ {
682 ++ g_assert_not_reached ();
683 ++ }
684 ++
685 ++#ifdef HAVE_LIBSYSTEMD
686 ++ if (sd_pid_get_session (pid, &session_str) == 0)
687 ++ {
688 ++ if (sd_session_get_seat (session_str, &seat_str) == 0)
689 ++ {
690 ++ /* do nothing */
691 ++ }
692 ++ }
693 ++#endif /* HAVE_LIBSYSTEMD */
694 ++
695 ++ g_assert (POLKIT_IS_UNIX_USER (user_for_subject));
696 ++ uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_for_subject));
697 ++
698 ++ groups = g_ptr_array_new_with_free_func (g_free);
699 ++
700 ++ passwd = getpwuid (uid);
701 ++ if (passwd == NULL)
702 ++ {
703 ++ user_name = g_strdup_printf ("%d", (gint) uid);
704 ++ g_warning ("Error looking up info for uid %d: %m", (gint) uid);
705 ++ }
706 ++ else
707 ++ {
708 ++ gid_t gids[512];
709 ++ int num_gids = 512;
710 ++
711 ++ user_name = g_strdup (passwd->pw_name);
712 ++
713 ++ if (getgrouplist (passwd->pw_name,
714 ++ passwd->pw_gid,
715 ++ gids,
716 ++ &num_gids) < 0)
717 ++ {
718 ++ g_warning ("Error looking up groups for uid %d: %m", (gint) uid);
719 ++ }
720 ++ else
721 ++ {
722 ++ gint n;
723 ++ for (n = 0; n < num_gids; n++)
724 ++ {
725 ++ struct group *group;
726 ++ group = getgrgid (gids[n]);
727 ++ if (group == NULL)
728 ++ {
729 ++ g_ptr_array_add (groups, g_strdup_printf ("%d", (gint) gids[n]));
730 ++ }
731 ++ else
732 ++ {
733 ++ g_ptr_array_add (groups, g_strdup (group->gr_name));
734 ++ }
735 ++ }
736 ++ }
737 ++ }
738 ++
739 ++ set_property_int32 (cx, "pid", pid);
740 ++ set_property_str (cx, "user", user_name);
741 ++ set_property_strv (cx, "groups", groups);
742 ++ set_property_str (cx, "seat", seat_str);
743 ++ set_property_str (cx, "session", session_str);
744 ++ set_property_bool (cx, "local", subject_is_local);
745 ++ set_property_bool (cx, "active", subject_is_active);
746 ++
747 ++ ret = TRUE;
748 ++
749 ++ out:
750 ++ free (session_str);
751 ++ free (seat_str);
752 ++ g_free (user_name);
753 ++ if (groups != NULL)
754 ++ g_ptr_array_unref (groups);
755 ++
756 ++ return ret;
757 ++}
758 ++
759 ++/* ---------------------------------------------------------------------------------------------------- */
760 ++
761 ++static gboolean
762 ++push_action_and_details (duk_context *cx,
763 ++ const gchar *action_id,
764 ++ PolkitDetails *details,
765 ++ GError **error)
766 ++{
767 ++ gchar **keys;
768 ++ guint n;
769 ++
770 ++ duk_get_global_string (cx, "Action");
771 ++ duk_new (cx, 0);
772 ++
773 ++ set_property_str (cx, "id", action_id);
774 ++
775 ++ keys = polkit_details_get_keys (details);
776 ++ for (n = 0; keys != NULL && keys[n] != NULL; n++)
777 ++ {
778 ++ gchar *key;
779 ++ const gchar *value;
780 ++ key = g_strdup_printf ("_detail_%s", keys[n]);
781 ++ value = polkit_details_lookup (details, keys[n]);
782 ++ set_property_str (cx, key, value);
783 ++ g_free (key);
784 ++ }
785 ++ g_strfreev (keys);
786 ++
787 ++ return TRUE;
788 ++}
789 ++
790 ++/* ---------------------------------------------------------------------------------------------------- */
791 ++
792 ++/* ---------------------------------------------------------------------------------------------------- */
793 ++
794 ++static GList *
795 ++polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
796 ++ PolkitSubject *caller,
797 ++ PolkitSubject *subject,
798 ++ PolkitIdentity *user_for_subject,
799 ++ gboolean subject_is_local,
800 ++ gboolean subject_is_active,
801 ++ const gchar *action_id,
802 ++ PolkitDetails *details)
803 ++{
804 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
805 ++ GList *ret = NULL;
806 ++ guint n;
807 ++ GError *error = NULL;
808 ++ const char *ret_str = NULL;
809 ++ gchar **ret_strs = NULL;
810 ++ duk_context *cx = authority->priv->cx;
811 ++
812 ++ duk_set_top (cx, 0);
813 ++ duk_get_global_string (cx, "polkit");
814 ++ duk_push_string (cx, "_runAdminRules");
815 ++
816 ++ if (!push_action_and_details (cx, action_id, details, &error))
817 ++ {
818 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
819 ++ "Error converting action and details to JS object: %s",
820 ++ error->message);
821 ++ g_clear_error (&error);
822 ++ goto out;
823 ++ }
824 ++
825 ++ if (!push_subject (cx, subject, user_for_subject, subject_is_local, subject_is_active, &error))
826 ++ {
827 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
828 ++ "Error converting subject to JS object: %s",
829 ++ error->message);
830 ++ g_clear_error (&error);
831 ++ goto out;
832 ++ }
833 ++
834 ++ if (duk_pcall_prop (cx, 0, 2) != DUK_ERR_NONE)
835 ++ {
836 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
837 ++ "Error evaluating admin rules: ",
838 ++ duk_safe_to_string (cx, -1));
839 ++ goto out;
840 ++ }
841 ++
842 ++ ret_str = duk_require_string (cx, -1);
843 ++
844 ++ ret_strs = g_strsplit (ret_str, ",", -1);
845 ++ for (n = 0; ret_strs != NULL && ret_strs[n] != NULL; n++)
846 ++ {
847 ++ const gchar *identity_str = ret_strs[n];
848 ++ PolkitIdentity *identity;
849 ++
850 ++ error = NULL;
851 ++ identity = polkit_identity_from_string (identity_str, &error);
852 ++ if (identity == NULL)
853 ++ {
854 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
855 ++ "Identity `%s' is not valid, ignoring: %s",
856 ++ identity_str, error->message);
857 ++ g_clear_error (&error);
858 ++ }
859 ++ else
860 ++ {
861 ++ ret = g_list_prepend (ret, identity);
862 ++ }
863 ++ }
864 ++ ret = g_list_reverse (ret);
865 ++
866 ++ out:
867 ++ g_strfreev (ret_strs);
868 ++ /* fallback to root password auth */
869 ++ if (ret == NULL)
870 ++ ret = g_list_prepend (ret, polkit_unix_user_new (0));
871 ++
872 ++ return ret;
873 ++}
874 ++
875 ++/* ---------------------------------------------------------------------------------------------------- */
876 ++
877 ++static PolkitImplicitAuthorization
878 ++polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
879 ++ PolkitSubject *caller,
880 ++ PolkitSubject *subject,
881 ++ PolkitIdentity *user_for_subject,
882 ++ gboolean subject_is_local,
883 ++ gboolean subject_is_active,
884 ++ const gchar *action_id,
885 ++ PolkitDetails *details,
886 ++ PolkitImplicitAuthorization implicit)
887 ++{
888 ++ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
889 ++ PolkitImplicitAuthorization ret = implicit;
890 ++ GError *error = NULL;
891 ++ gchar *ret_str = NULL;
892 ++ gboolean good = FALSE;
893 ++ duk_context *cx = authority->priv->cx;
894 ++
895 ++ duk_set_top (cx, 0);
896 ++ duk_get_global_string (cx, "polkit");
897 ++ duk_push_string (cx, "_runRules");
898 ++
899 ++ if (!push_action_and_details (cx, action_id, details, &error))
900 ++ {
901 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
902 ++ "Error converting action and details to JS object: %s",
903 ++ error->message);
904 ++ g_clear_error (&error);
905 ++ goto out;
906 ++ }
907 ++
908 ++ if (!push_subject (cx, subject, user_for_subject, subject_is_local, subject_is_active, &error))
909 ++ {
910 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
911 ++ "Error converting subject to JS object: %s",
912 ++ error->message);
913 ++ g_clear_error (&error);
914 ++ goto out;
915 ++ }
916 ++
917 ++ if (duk_pcall_prop (cx, 0, 2) != DUK_ERR_NONE)
918 ++ {
919 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
920 ++ "Error evaluating authorization rules: ",
921 ++ duk_safe_to_string (cx, -1));
922 ++ goto out;
923 ++ }
924 ++
925 ++ if (duk_is_null(cx, -1)) {
926 ++ good = TRUE;
927 ++ goto out;
928 ++ }
929 ++ ret_str = g_strdup (duk_require_string (cx, -1));
930 ++ if (!polkit_implicit_authorization_from_string (ret_str, &ret))
931 ++ {
932 ++ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
933 ++ "Returned result `%s' is not valid",
934 ++ ret_str);
935 ++ goto out;
936 ++ }
937 ++
938 ++ good = TRUE;
939 ++
940 ++ out:
941 ++ if (!good)
942 ++ ret = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
943 ++ g_free (ret_str);
944 ++
945 ++ return ret;
946 ++}
947 ++
948 ++/* ---------------------------------------------------------------------------------------------------- */
949 ++
950 ++static duk_ret_t
951 ++js_polkit_log (duk_context *cx)
952 ++{
953 ++ const char *str = duk_require_string (cx, 0);
954 ++ fprintf (stderr, "%s\n", str);
955 ++ return 0;
956 ++}
957 ++
958 ++/* ---------------------------------------------------------------------------------------------------- */
959 ++
960 ++static const gchar *
961 ++get_signal_name (gint signal_number)
962 ++{
963 ++ switch (signal_number)
964 ++ {
965 ++#define _HANDLE_SIG(sig) case sig: return #sig;
966 ++ _HANDLE_SIG (SIGHUP);
967 ++ _HANDLE_SIG (SIGINT);
968 ++ _HANDLE_SIG (SIGQUIT);
969 ++ _HANDLE_SIG (SIGILL);
970 ++ _HANDLE_SIG (SIGABRT);
971 ++ _HANDLE_SIG (SIGFPE);
972 ++ _HANDLE_SIG (SIGKILL);
973 ++ _HANDLE_SIG (SIGSEGV);
974 ++ _HANDLE_SIG (SIGPIPE);
975 ++ _HANDLE_SIG (SIGALRM);
976 ++ _HANDLE_SIG (SIGTERM);
977 ++ _HANDLE_SIG (SIGUSR1);
978 ++ _HANDLE_SIG (SIGUSR2);
979 ++ _HANDLE_SIG (SIGCHLD);
980 ++ _HANDLE_SIG (SIGCONT);
981 ++ _HANDLE_SIG (SIGSTOP);
982 ++ _HANDLE_SIG (SIGTSTP);
983 ++ _HANDLE_SIG (SIGTTIN);
984 ++ _HANDLE_SIG (SIGTTOU);
985 ++ _HANDLE_SIG (SIGBUS);
986 ++#ifdef SIGPOLL
987 ++ _HANDLE_SIG (SIGPOLL);
988 ++#endif
989 ++ _HANDLE_SIG (SIGPROF);
990 ++ _HANDLE_SIG (SIGSYS);
991 ++ _HANDLE_SIG (SIGTRAP);
992 ++ _HANDLE_SIG (SIGURG);
993 ++ _HANDLE_SIG (SIGVTALRM);
994 ++ _HANDLE_SIG (SIGXCPU);
995 ++ _HANDLE_SIG (SIGXFSZ);
996 ++#undef _HANDLE_SIG
997 ++ default:
998 ++ break;
999 ++ }
1000 ++ return "UNKNOWN_SIGNAL";
1001 ++}
1002 ++
1003 ++typedef struct
1004 ++{
1005 ++ GMainLoop *loop;
1006 ++ GAsyncResult *res;
1007 ++} SpawnData;
1008 ++
1009 ++static void
1010 ++spawn_cb (GObject *source_object,
1011 ++ GAsyncResult *res,
1012 ++ gpointer user_data)
1013 ++{
1014 ++ SpawnData *data = user_data;
1015 ++ data->res = g_object_ref (res);
1016 ++ g_main_loop_quit (data->loop);
1017 ++}
1018 ++
1019 ++static duk_ret_t
1020 ++js_polkit_spawn (duk_context *cx)
1021 ++{
1022 ++#if (DUK_VERSION >= 20000)
1023 ++ duk_ret_t ret = DUK_RET_ERROR;
1024 ++#else
1025 ++ duk_ret_t ret = DUK_RET_INTERNAL_ERROR;
1026 ++#endif
1027 ++ gchar *standard_output = NULL;
1028 ++ gchar *standard_error = NULL;
1029 ++ gint exit_status;
1030 ++ GError *error = NULL;
1031 ++ guint32 array_len;
1032 ++ gchar **argv = NULL;
1033 ++ GMainContext *context = NULL;
1034 ++ GMainLoop *loop = NULL;
1035 ++ SpawnData data = {0};
1036 ++ char *err_str = NULL;
1037 ++ guint n;
1038 ++
1039 ++ if (!duk_is_array (cx, 0))
1040 ++ goto out;
1041 ++
1042 ++ array_len = duk_get_length (cx, 0);
1043 ++
1044 ++ argv = g_new0 (gchar*, array_len + 1);
1045 ++ for (n = 0; n < array_len; n++)
1046 ++ {
1047 ++ duk_get_prop_index (cx, 0, n);
1048 ++ argv[n] = g_strdup (duk_to_string (cx, -1));
1049 ++ duk_pop (cx);
1050 ++ }
1051 ++
1052 ++ context = g_main_context_new ();
1053 ++ loop = g_main_loop_new (context, FALSE);
1054 ++
1055 ++ g_main_context_push_thread_default (context);
1056 ++
1057 ++ data.loop = loop;
1058 ++ utils_spawn ((const gchar *const *) argv,
1059 ++ 10, /* timeout_seconds */
1060 ++ NULL, /* cancellable */
1061 ++ spawn_cb,
1062 ++ &data);
1063 ++
1064 ++ g_main_loop_run (loop);
1065 ++
1066 ++ g_main_context_pop_thread_default (context);
1067 ++
1068 ++ if (!utils_spawn_finish (data.res,
1069 ++ &exit_status,
1070 ++ &standard_output,
1071 ++ &standard_error,
1072 ++ &error))
1073 ++ {
1074 ++ err_str = g_strdup_printf ("Error spawning helper: %s (%s, %d)",
1075 ++ error->message, g_quark_to_string (error->domain), error->code);
1076 ++ g_clear_error (&error);
1077 ++ goto out;
1078 ++ }
1079 ++
1080 ++ if (!(WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0))
1081 ++ {
1082 ++ GString *gstr;
1083 ++ gstr = g_string_new (NULL);
1084 ++ if (WIFEXITED (exit_status))
1085 ++ {
1086 ++ g_string_append_printf (gstr,
1087 ++ "Helper exited with non-zero exit status %d",
1088 ++ WEXITSTATUS (exit_status));
1089 ++ }
1090 ++ else if (WIFSIGNALED (exit_status))
1091 ++ {
1092 ++ g_string_append_printf (gstr,
1093 ++ "Helper was signaled with signal %s (%d)",
1094 ++ get_signal_name (WTERMSIG (exit_status)),
1095 ++ WTERMSIG (exit_status));
1096 ++ }
1097 ++ g_string_append_printf (gstr, ", stdout=`%s', stderr=`%s'",
1098 ++ standard_output, standard_error);
1099 ++ err_str = g_string_free (gstr, FALSE);
1100 ++ goto out;
1101 ++ }
1102 ++
1103 ++ duk_push_string (cx, standard_output);
1104 ++ ret = 1;
1105 ++
1106 ++ out:
1107 ++ g_strfreev (argv);
1108 ++ g_free (standard_output);
1109 ++ g_free (standard_error);
1110 ++ g_clear_object (&data.res);
1111 ++ if (loop != NULL)
1112 ++ g_main_loop_unref (loop);
1113 ++ if (context != NULL)
1114 ++ g_main_context_unref (context);
1115 ++
1116 ++ if (err_str)
1117 ++ duk_error (cx, DUK_ERR_ERROR, err_str);
1118 ++
1119 ++ return ret;
1120 ++}
1121 ++
1122 ++/* ---------------------------------------------------------------------------------------------------- */
1123 ++
1124 ++
1125 ++static duk_ret_t
1126 ++js_polkit_user_is_in_netgroup (duk_context *cx)
1127 ++{
1128 ++ const char *user;
1129 ++ const char *netgroup;
1130 ++ gboolean is_in_netgroup = FALSE;
1131 ++
1132 ++ user = duk_require_string (cx, 0);
1133 ++ netgroup = duk_require_string (cx, 1);
1134 ++
1135 ++#ifdef HAVE_SETNETGRENT
1136 ++ if (innetgr (netgroup,
1137 ++ NULL, /* host */
1138 ++ user,
1139 ++ NULL)) /* domain */
1140 ++ {
1141 ++ is_in_netgroup = TRUE;
1142 ++ }
1143 ++#endif
1144 ++
1145 ++ duk_push_boolean (cx, is_in_netgroup);
1146 ++ return 1;
1147 ++}
1148 ++
1149 ++/* ---------------------------------------------------------------------------------------------------- */
1150 ++
1151 ++typedef struct
1152 ++{
1153 ++ GSimpleAsyncResult *simple; /* borrowed reference */
1154 ++ GMainContext *main_context; /* may be NULL */
1155 ++
1156 ++ GCancellable *cancellable; /* may be NULL */
1157 ++ gulong cancellable_handler_id;
1158 ++
1159 ++ GPid child_pid;
1160 ++ gint child_stdout_fd;
1161 ++ gint child_stderr_fd;
1162 ++
1163 ++ GIOChannel *child_stdout_channel;
1164 ++ GIOChannel *child_stderr_channel;
1165 ++
1166 ++ GSource *child_watch_source;
1167 ++ GSource *child_stdout_source;
1168 ++ GSource *child_stderr_source;
1169 ++
1170 ++ guint timeout_seconds;
1171 ++ gboolean timed_out;
1172 ++ GSource *timeout_source;
1173 ++
1174 ++ GString *child_stdout;
1175 ++ GString *child_stderr;
1176 ++
1177 ++ gint exit_status;
1178 ++} UtilsSpawnData;
1179 ++
1180 ++static void
1181 ++utils_child_watch_from_release_cb (GPid pid,
1182 ++ gint status,
1183 ++ gpointer user_data)
1184 ++{
1185 ++}
1186 ++
1187 ++static void
1188 ++utils_spawn_data_free (UtilsSpawnData *data)
1189 ++{
1190 ++ if (data->timeout_source != NULL)
1191 ++ {
1192 ++ g_source_destroy (data->timeout_source);
1193 ++ data->timeout_source = NULL;
1194 ++ }
1195 ++
1196 ++ /* Nuke the child, if necessary */
1197 ++ if (data->child_watch_source != NULL)
1198 ++ {
1199 ++ g_source_destroy (data->child_watch_source);
1200 ++ data->child_watch_source = NULL;
1201 ++ }
1202 ++
1203 ++ if (data->child_pid != 0)
1204 ++ {
1205 ++ GSource *source;
1206 ++ kill (data->child_pid, SIGTERM);
1207 ++ /* OK, we need to reap for the child ourselves - we don't want
1208 ++ * to use waitpid() because that might block the calling
1209 ++ * thread (the child might handle SIGTERM and use several
1210 ++ * seconds for cleanup/rollback).
1211 ++ *
1212 ++ * So we use GChildWatch instead.
1213 ++ *
1214 ++ * Avoid taking a references to ourselves. but note that we need
1215 ++ * to pass the GSource so we can nuke it once handled.
1216 ++ */
1217 ++ source = g_child_watch_source_new (data->child_pid);
1218 ++ g_source_set_callback (source,
1219 ++ (GSourceFunc) utils_child_watch_from_release_cb,
1220 ++ source,
1221 ++ (GDestroyNotify) g_source_destroy);
1222 ++ g_source_attach (source, data->main_context);
1223 ++ g_source_unref (source);
1224 ++ data->child_pid = 0;
1225 ++ }
1226 ++
1227 ++ if (data->child_stdout != NULL)
1228 ++ {
1229 ++ g_string_free (data->child_stdout, TRUE);
1230 ++ data->child_stdout = NULL;
1231 ++ }
1232 ++
1233 ++ if (data->child_stderr != NULL)
1234 ++ {
1235 ++ g_string_free (data->child_stderr, TRUE);
1236 ++ data->child_stderr = NULL;
1237 ++ }
1238 ++
1239 ++ if (data->child_stdout_channel != NULL)
1240 ++ {
1241 ++ g_io_channel_unref (data->child_stdout_channel);
1242 ++ data->child_stdout_channel = NULL;
1243 ++ }
1244 ++ if (data->child_stderr_channel != NULL)
1245 ++ {
1246 ++ g_io_channel_unref (data->child_stderr_channel);
1247 ++ data->child_stderr_channel = NULL;
1248 ++ }
1249 ++
1250 ++ if (data->child_stdout_source != NULL)
1251 ++ {
1252 ++ g_source_destroy (data->child_stdout_source);
1253 ++ data->child_stdout_source = NULL;
1254 ++ }
1255 ++ if (data->child_stderr_source != NULL)
1256 ++ {
1257 ++ g_source_destroy (data->child_stderr_source);
1258 ++ data->child_stderr_source = NULL;
1259 ++ }
1260 ++
1261 ++ if (data->child_stdout_fd != -1)
1262 ++ {
1263 ++ g_warn_if_fail (close (data->child_stdout_fd) == 0);
1264 ++ data->child_stdout_fd = -1;
1265 ++ }
1266 ++ if (data->child_stderr_fd != -1)
1267 ++ {
1268 ++ g_warn_if_fail (close (data->child_stderr_fd) == 0);
1269 ++ data->child_stderr_fd = -1;
1270 ++ }
1271 ++
1272 ++ if (data->cancellable_handler_id > 0)
1273 ++ {
1274 ++ g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
1275 ++ data->cancellable_handler_id = 0;
1276 ++ }
1277 ++
1278 ++ if (data->main_context != NULL)
1279 ++ g_main_context_unref (data->main_context);
1280 ++
1281 ++ if (data->cancellable != NULL)
1282 ++ g_object_unref (data->cancellable);
1283 ++
1284 ++ g_slice_free (UtilsSpawnData, data);
1285 ++}
1286 ++
1287 ++/* called in the thread where @cancellable was cancelled */
1288 ++static void
1289 ++utils_on_cancelled (GCancellable *cancellable,
1290 ++ gpointer user_data)
1291 ++{
1292 ++ UtilsSpawnData *data = user_data;
1293 ++ GError *error;
1294 ++
1295 ++ error = NULL;
1296 ++ g_warn_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
1297 ++ g_simple_async_result_take_error (data->simple, error);
1298 ++ g_simple_async_result_complete_in_idle (data->simple);
1299 ++ g_object_unref (data->simple);
1300 ++}
1301 ++
1302 ++static gboolean
1303 ++utils_read_child_stderr (GIOChannel *channel,
1304 ++ GIOCondition condition,
1305 ++ gpointer user_data)
1306 ++{
1307 ++ UtilsSpawnData *data = user_data;
1308 ++ gchar buf[1024];
1309 ++ gsize bytes_read;
1310 ++
1311 ++ g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
1312 ++ g_string_append_len (data->child_stderr, buf, bytes_read);
1313 ++ return TRUE;
1314 ++}
1315 ++
1316 ++static gboolean
1317 ++utils_read_child_stdout (GIOChannel *channel,
1318 ++ GIOCondition condition,
1319 ++ gpointer user_data)
1320 ++{
1321 ++ UtilsSpawnData *data = user_data;
1322 ++ gchar buf[1024];
1323 ++ gsize bytes_read;
1324 ++
1325 ++ g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
1326 ++ g_string_append_len (data->child_stdout, buf, bytes_read);
1327 ++ return TRUE;
1328 ++}
1329 ++
1330 ++static void
1331 ++utils_child_watch_cb (GPid pid,
1332 ++ gint status,
1333 ++ gpointer user_data)
1334 ++{
1335 ++ UtilsSpawnData *data = user_data;
1336 ++ gchar *buf;
1337 ++ gsize buf_size;
1338 ++
1339 ++ if (g_io_channel_read_to_end (data->child_stdout_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
1340 ++ {
1341 ++ g_string_append_len (data->child_stdout, buf, buf_size);
1342 ++ g_free (buf);
1343 ++ }
1344 ++ if (g_io_channel_read_to_end (data->child_stderr_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
1345 ++ {
1346 ++ g_string_append_len (data->child_stderr, buf, buf_size);
1347 ++ g_free (buf);
1348 ++ }
1349 ++
1350 ++ data->exit_status = status;
1351 ++
1352 ++ /* ok, child watch is history, make sure we don't free it in spawn_data_free() */
1353 ++ data->child_pid = 0;
1354 ++ data->child_watch_source = NULL;
1355 ++
1356 ++ /* we're done */
1357 ++ g_simple_async_result_complete_in_idle (data->simple);
1358 ++ g_object_unref (data->simple);
1359 ++}
1360 ++
1361 ++static gboolean
1362 ++utils_timeout_cb (gpointer user_data)
1363 ++{
1364 ++ UtilsSpawnData *data = user_data;
1365 ++
1366 ++ data->timed_out = TRUE;
1367 ++
1368 ++ /* ok, timeout is history, make sure we don't free it in spawn_data_free() */
1369 ++ data->timeout_source = NULL;
1370 ++
1371 ++ /* we're done */
1372 ++ g_simple_async_result_complete_in_idle (data->simple);
1373 ++ g_object_unref (data->simple);
1374 ++
1375 ++ return FALSE; /* remove source */
1376 ++}
1377 ++
1378 ++static void
1379 ++utils_spawn (const gchar *const *argv,
1380 ++ guint timeout_seconds,
1381 ++ GCancellable *cancellable,
1382 ++ GAsyncReadyCallback callback,
1383 ++ gpointer user_data)
1384 ++{
1385 ++ UtilsSpawnData *data;
1386 ++ GError *error;
1387 ++
1388 ++ data = g_slice_new0 (UtilsSpawnData);
1389 ++ data->timeout_seconds = timeout_seconds;
1390 ++ data->simple = g_simple_async_result_new (NULL,
1391 ++ callback,
1392 ++ user_data,
1393 ++ utils_spawn);
1394 ++ data->main_context = g_main_context_get_thread_default ();
1395 ++ if (data->main_context != NULL)
1396 ++ g_main_context_ref (data->main_context);
1397 ++
1398 ++ data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1399 ++
1400 ++ data->child_stdout = g_string_new (NULL);
1401 ++ data->child_stderr = g_string_new (NULL);
1402 ++ data->child_stdout_fd = -1;
1403 ++ data->child_stderr_fd = -1;
1404 ++
1405 ++ /* the life-cycle of UtilsSpawnData is tied to its GSimpleAsyncResult */
1406 ++ g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) utils_spawn_data_free);
1407 ++
1408 ++ error = NULL;
1409 ++ if (data->cancellable != NULL)
1410 ++ {
1411 ++ /* could already be cancelled */
1412 ++ error = NULL;
1413 ++ if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
1414 ++ {
1415 ++ g_simple_async_result_take_error (data->simple, error);
1416 ++ g_simple_async_result_complete_in_idle (data->simple);
1417 ++ g_object_unref (data->simple);
1418 ++ goto out;
1419 ++ }
1420 ++
1421 ++ data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
1422 ++ G_CALLBACK (utils_on_cancelled),
1423 ++ data,
1424 ++ NULL);
1425 ++ }
1426 ++
1427 ++ error = NULL;
1428 ++ if (!g_spawn_async_with_pipes (NULL, /* working directory */
1429 ++ (gchar **) argv,
1430 ++ NULL, /* envp */
1431 ++ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
1432 ++ NULL, /* child_setup */
1433 ++ NULL, /* child_setup's user_data */
1434 ++ &(data->child_pid),
1435 ++ NULL, /* gint *stdin_fd */
1436 ++ &(data->child_stdout_fd),
1437 ++ &(data->child_stderr_fd),
1438 ++ &error))
1439 ++ {
1440 ++ g_prefix_error (&error, "Error spawning: ");
1441 ++ g_simple_async_result_take_error (data->simple, error);
1442 ++ g_simple_async_result_complete_in_idle (data->simple);
1443 ++ g_object_unref (data->simple);
1444 ++ goto out;
1445 ++ }
1446 ++
1447 ++ if (timeout_seconds > 0)
1448 ++ {
1449 ++ data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
1450 ++ g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
1451 ++ g_source_set_callback (data->timeout_source, utils_timeout_cb, data, NULL);
1452 ++ g_source_attach (data->timeout_source, data->main_context);
1453 ++ g_source_unref (data->timeout_source);
1454 ++ }
1455 ++
1456 ++ data->child_watch_source = g_child_watch_source_new (data->child_pid);
1457 ++ g_source_set_callback (data->child_watch_source, (GSourceFunc) utils_child_watch_cb, data, NULL);
1458 ++ g_source_attach (data->child_watch_source, data->main_context);
1459 ++ g_source_unref (data->child_watch_source);
1460 ++
1461 ++ data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
1462 ++ g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
1463 ++ data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
1464 ++ g_source_set_callback (data->child_stdout_source, (GSourceFunc) utils_read_child_stdout, data, NULL);
1465 ++ g_source_attach (data->child_stdout_source, data->main_context);
1466 ++ g_source_unref (data->child_stdout_source);
1467 ++
1468 ++ data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
1469 ++ g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
1470 ++ data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
1471 ++ g_source_set_callback (data->child_stderr_source, (GSourceFunc) utils_read_child_stderr, data, NULL);
1472 ++ g_source_attach (data->child_stderr_source, data->main_context);
1473 ++ g_source_unref (data->child_stderr_source);
1474 ++
1475 ++ out:
1476 ++ ;
1477 ++}
1478 ++
1479 ++gboolean
1480 ++utils_spawn_finish (GAsyncResult *res,
1481 ++ gint *out_exit_status,
1482 ++ gchar **out_standard_output,
1483 ++ gchar **out_standard_error,
1484 ++ GError **error)
1485 ++{
1486 ++ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1487 ++ UtilsSpawnData *data;
1488 ++ gboolean ret = FALSE;
1489 ++
1490 ++ g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
1491 ++ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1492 ++
1493 ++ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == utils_spawn);
1494 ++
1495 ++ if (g_simple_async_result_propagate_error (simple, error))
1496 ++ goto out;
1497 ++
1498 ++ data = g_simple_async_result_get_op_res_gpointer (simple);
1499 ++
1500 ++ if (data->timed_out)
1501 ++ {
1502 ++ g_set_error (error,
1503 ++ G_IO_ERROR,
1504 ++ G_IO_ERROR_TIMED_OUT,
1505 ++ "Timed out after %d seconds",
1506 ++ data->timeout_seconds);
1507 ++ goto out;
1508 ++ }
1509 ++
1510 ++ if (out_exit_status != NULL)
1511 ++ *out_exit_status = data->exit_status;
1512 ++
1513 ++ if (out_standard_output != NULL)
1514 ++ *out_standard_output = g_strdup (data->child_stdout->str);
1515 ++
1516 ++ if (out_standard_error != NULL)
1517 ++ *out_standard_error = g_strdup (data->child_stderr->str);
1518 ++
1519 ++ ret = TRUE;
1520 ++
1521 ++ out:
1522 ++ return ret;
1523 ++}
1524
1525 diff --git a/sys-auth/polkit/files/polkit-0.118-elogind.patch b/sys-auth/polkit/files/polkit-0.118-elogind.patch
1526 new file mode 100644
1527 index 0000000..93d6720
1528 --- /dev/null
1529 +++ b/sys-auth/polkit/files/polkit-0.118-elogind.patch
1530 @@ -0,0 +1,28 @@
1531 +From 08bb656496cd3d6213bbe9473f63f2d4a110da6e Mon Sep 17 00:00:00 2001
1532 +From: Rasmus Thomsen <cogitri@×××××××.org>
1533 +Date: Wed, 11 Apr 2018 13:14:14 +0200
1534 +Subject: [PATCH] configure: fix elogind support
1535 +
1536 +HAVE_LIBSYSTEMD is used to determine which source files to use.
1537 +We have to check if either have_libsystemd or have_libelogind is
1538 +true, as both of these need the source files which are used when
1539 +HAVE_LIBSYSTEMD is true.
1540 +---
1541 + configure.ac | 2 +-
1542 + 1 file changed, 1 insertion(+), 1 deletion(-)
1543 +
1544 +diff --git a/configure.ac b/configure.ac
1545 +index 36df239..da47ecb 100644
1546 +--- a/configure.ac
1547 ++++ b/configure.ac
1548 +@@ -221,7 +221,7 @@ AS_IF([test "x$cross_compiling" != "xyes" ], [
1549 +
1550 + AC_SUBST(LIBSYSTEMD_CFLAGS)
1551 + AC_SUBST(LIBSYSTEMD_LIBS)
1552 +-AM_CONDITIONAL(HAVE_LIBSYSTEMD, [test "$have_libsystemd" = "yes"], [Using libsystemd])
1553 ++AM_CONDITIONAL(HAVE_LIBSYSTEMD, [test "$have_libsystemd" = "yes" || test "$have_libelogind" = "yes" ], [Using libsystemd])
1554 +
1555 + dnl ---------------------------------------------------------------------------
1556 + dnl - systemd unit / service files
1557 +--
1558 +2.17.0
1559
1560 diff --git a/sys-auth/polkit/files/polkit-0.118-make-netgroup-support-optional.patch b/sys-auth/polkit/files/polkit-0.118-make-netgroup-support-optional.patch
1561 new file mode 100644
1562 index 0000000..aef30ef
1563 --- /dev/null
1564 +++ b/sys-auth/polkit/files/polkit-0.118-make-netgroup-support-optional.patch
1565 @@ -0,0 +1,219 @@
1566 +diff --git a/configure.ac b/configure.ac
1567 +index 4809dc9..d1ea325 100644
1568 +--- a/configure.ac
1569 ++++ b/configure.ac
1570 +@@ -100,7 +100,7 @@ AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"],
1571 + [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
1572 + AC_SUBST(EXPAT_LIBS)
1573 +
1574 +-AC_CHECK_FUNCS(clearenv fdatasync)
1575 ++AC_CHECK_FUNCS(clearenv fdatasync setnetgrent)
1576 +
1577 + if test "x$GCC" = "xyes"; then
1578 + LDFLAGS="-Wl,--as-needed $LDFLAGS"
1579 +diff --git a/src/polkit/polkitidentity.c b/src/polkit/polkitidentity.c
1580 +index 3aa1f7f..793f17d 100644
1581 +--- a/src/polkit/polkitidentity.c
1582 ++++ b/src/polkit/polkitidentity.c
1583 +@@ -182,7 +182,15 @@ polkit_identity_from_string (const gchar *str,
1584 + }
1585 + else if (g_str_has_prefix (str, "unix-netgroup:"))
1586 + {
1587 ++#ifndef HAVE_SETNETGRENT
1588 ++ g_set_error (error,
1589 ++ POLKIT_ERROR,
1590 ++ POLKIT_ERROR_FAILED,
1591 ++ "Netgroups are not available on this machine ('%s')",
1592 ++ str);
1593 ++#else
1594 + identity = polkit_unix_netgroup_new (str + sizeof "unix-netgroup:" - 1);
1595 ++#endif
1596 + }
1597 +
1598 + if (identity == NULL && (error != NULL && *error == NULL))
1599 +@@ -344,6 +352,14 @@ polkit_identity_new_for_gvariant (GVariant *variant,
1600 + GVariant *v;
1601 + const char *name;
1602 +
1603 ++#ifndef HAVE_SETNETGRENT
1604 ++ g_set_error (error,
1605 ++ POLKIT_ERROR,
1606 ++ POLKIT_ERROR_FAILED,
1607 ++ "Netgroups are not available on this machine");
1608 ++ goto out;
1609 ++#else
1610 ++
1611 + v = lookup_asv (details_gvariant, "name", G_VARIANT_TYPE_STRING, error);
1612 + if (v == NULL)
1613 + {
1614 +@@ -353,6 +369,7 @@ polkit_identity_new_for_gvariant (GVariant *variant,
1615 + name = g_variant_get_string (v, NULL);
1616 + ret = polkit_unix_netgroup_new (name);
1617 + g_variant_unref (v);
1618 ++#endif
1619 + }
1620 + else
1621 + {
1622 +diff --git a/src/polkit/polkitunixnetgroup.c b/src/polkit/polkitunixnetgroup.c
1623 +index 8a2b369..83f8d4a 100644
1624 +--- a/src/polkit/polkitunixnetgroup.c
1625 ++++ b/src/polkit/polkitunixnetgroup.c
1626 +@@ -194,6 +194,9 @@ polkit_unix_netgroup_set_name (PolkitUnixNetgroup *group,
1627 + PolkitIdentity *
1628 + polkit_unix_netgroup_new (const gchar *name)
1629 + {
1630 ++#ifndef HAVE_SETNETGRENT
1631 ++ g_assert_not_reached();
1632 ++#endif
1633 + g_return_val_if_fail (name != NULL, NULL);
1634 + return POLKIT_IDENTITY (g_object_new (POLKIT_TYPE_UNIX_NETGROUP,
1635 + "name", name,
1636 +diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
1637 +index 056d9a8..36c2f3d 100644
1638 +--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
1639 ++++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
1640 +@@ -2233,25 +2233,26 @@ get_users_in_net_group (PolkitIdentity *group,
1641 + GList *ret;
1642 +
1643 + ret = NULL;
1644 ++#ifdef HAVE_SETNETGRENT
1645 + name = polkit_unix_netgroup_get_name (POLKIT_UNIX_NETGROUP (group));
1646 +
1647 +-#ifdef HAVE_SETNETGRENT_RETURN
1648 ++# ifdef HAVE_SETNETGRENT_RETURN
1649 + if (setnetgrent (name) == 0)
1650 + {
1651 + g_warning ("Error looking up net group with name %s: %s", name, g_strerror (errno));
1652 + goto out;
1653 + }
1654 +-#else
1655 ++# else
1656 + setnetgrent (name);
1657 +-#endif
1658 ++# endif /* HAVE_SETNETGRENT_RETURN */
1659 +
1660 + for (;;)
1661 + {
1662 +-#if defined(HAVE_NETBSD) || defined(HAVE_OPENBSD)
1663 ++# if defined(HAVE_NETBSD) || defined(HAVE_OPENBSD)
1664 + const char *hostname, *username, *domainname;
1665 +-#else
1666 ++# else
1667 + char *hostname, *username, *domainname;
1668 +-#endif
1669 ++# endif /* defined(HAVE_NETBSD) || defined(HAVE_OPENBSD) */
1670 + PolkitIdentity *user;
1671 + GError *error = NULL;
1672 +
1673 +@@ -2282,6 +2283,7 @@ get_users_in_net_group (PolkitIdentity *group,
1674 +
1675 + out:
1676 + endnetgrent ();
1677 ++#endif /* HAVE_SETNETGRENT */
1678 + return ret;
1679 + }
1680 +
1681 +diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
1682 +index 1d91103..366cbdf 100644
1683 +--- a/src/polkitbackend/polkitbackendjsauthority.cpp
1684 ++++ b/src/polkitbackend/polkitbackendjsauthority.cpp
1685 +@@ -1519,6 +1519,7 @@ js_polkit_user_is_in_netgroup (JSContext *cx,
1686 +
1687 + JS::CallArgs args = JS::CallArgsFromVp (argc, vp);
1688 +
1689 ++#ifdef HAVE_SETNETGRENT
1690 + JS::RootedString usrstr (authority->priv->cx);
1691 + usrstr = args[0].toString();
1692 + user = JS_EncodeStringToUTF8 (cx, usrstr);
1693 +@@ -1533,6 +1534,7 @@ js_polkit_user_is_in_netgroup (JSContext *cx,
1694 + {
1695 + is_in_netgroup = true;
1696 + }
1697 ++#endif
1698 +
1699 + ret = true;
1700 +
1701 +diff --git a/test/polkit/polkitidentitytest.c b/test/polkit/polkitidentitytest.c
1702 +index e91967b..e829aaa 100644
1703 +--- a/test/polkit/polkitidentitytest.c
1704 ++++ b/test/polkit/polkitidentitytest.c
1705 +@@ -19,6 +19,7 @@
1706 + * Author: Nikki VonHollen <vonhollen@××××××.com>
1707 + */
1708 +
1709 ++#include "config.h"
1710 + #include "glib.h"
1711 + #include <polkit/polkit.h>
1712 + #include <polkit/polkitprivate.h>
1713 +@@ -145,11 +146,15 @@ struct ComparisonTestData comparison_test_data [] = {
1714 + {"unix-group:root", "unix-group:jane", FALSE},
1715 + {"unix-group:jane", "unix-group:jane", TRUE},
1716 +
1717 ++#ifdef HAVE_SETNETGRENT
1718 + {"unix-netgroup:foo", "unix-netgroup:foo", TRUE},
1719 + {"unix-netgroup:foo", "unix-netgroup:bar", FALSE},
1720 ++#endif
1721 +
1722 + {"unix-user:root", "unix-group:root", FALSE},
1723 ++#ifdef HAVE_SETNETGRENT
1724 + {"unix-user:jane", "unix-netgroup:foo", FALSE},
1725 ++#endif
1726 +
1727 + {NULL},
1728 + };
1729 +@@ -181,11 +186,13 @@ main (int argc, char *argv[])
1730 + g_test_add_data_func ("/PolkitIdentity/group_string_2", "unix-group:jane", test_string);
1731 + g_test_add_data_func ("/PolkitIdentity/group_string_3", "unix-group:users", test_string);
1732 +
1733 ++#ifdef HAVE_SETNETGRENT
1734 + g_test_add_data_func ("/PolkitIdentity/netgroup_string", "unix-netgroup:foo", test_string);
1735 ++ g_test_add_data_func ("/PolkitIdentity/netgroup_gvariant", "unix-netgroup:foo", test_gvariant);
1736 ++#endif
1737 +
1738 + g_test_add_data_func ("/PolkitIdentity/user_gvariant", "unix-user:root", test_gvariant);
1739 + g_test_add_data_func ("/PolkitIdentity/group_gvariant", "unix-group:root", test_gvariant);
1740 +- g_test_add_data_func ("/PolkitIdentity/netgroup_gvariant", "unix-netgroup:foo", test_gvariant);
1741 +
1742 + add_comparison_tests ();
1743 +
1744 +diff --git a/test/polkit/polkitunixnetgrouptest.c b/test/polkit/polkitunixnetgrouptest.c
1745 +index 3701ba1..e3352eb 100644
1746 +--- a/test/polkit/polkitunixnetgrouptest.c
1747 ++++ b/test/polkit/polkitunixnetgrouptest.c
1748 +@@ -19,6 +19,7 @@
1749 + * Author: Nikki VonHollen <vonhollen@××××××.com>
1750 + */
1751 +
1752 ++#include "config.h"
1753 + #include "glib.h"
1754 + #include <polkit/polkit.h>
1755 + #include <string.h>
1756 +@@ -69,7 +70,9 @@ int
1757 + main (int argc, char *argv[])
1758 + {
1759 + g_test_init (&argc, &argv, NULL);
1760 ++#ifdef HAVE_SETNETGRENT
1761 + g_test_add_func ("/PolkitUnixNetgroup/new", test_new);
1762 + g_test_add_func ("/PolkitUnixNetgroup/set_name", test_set_name);
1763 ++#endif
1764 + return g_test_run ();
1765 + }
1766 +diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
1767 +index 71aad23..fdd28f3 100644
1768 +--- a/test/polkitbackend/test-polkitbackendjsauthority.c
1769 ++++ b/test/polkitbackend/test-polkitbackendjsauthority.c
1770 +@@ -137,12 +137,14 @@ test_get_admin_identities (void)
1771 + "unix-group:users"
1772 + }
1773 + },
1774 ++#ifdef HAVE_SETNETGRENT
1775 + {
1776 + "net.company.action3",
1777 + {
1778 + "unix-netgroup:foo"
1779 + }
1780 + },
1781 ++#endif
1782 + };
1783 + guint n;
1784 +
1785
1786 diff --git a/sys-auth/polkit/polkit-0.118-r1.ebuild b/sys-auth/polkit/polkit-0.118-r1.ebuild
1787 new file mode 100644
1788 index 0000000..d70a384
1789 --- /dev/null
1790 +++ b/sys-auth/polkit/polkit-0.118-r1.ebuild
1791 @@ -0,0 +1,134 @@
1792 +# Copyright 1999-2020 Gentoo Authors
1793 +# Distributed under the terms of the GNU General Public License v2
1794 +
1795 +EAPI=7
1796 +
1797 +inherit autotools pam pax-utils systemd xdg-utils
1798 +
1799 +DESCRIPTION="Policy framework for controlling privileges for system-wide services"
1800 +HOMEPAGE="https://www.freedesktop.org/wiki/Software/polkit https://gitlab.freedesktop.org/polkit/polkit"
1801 +SRC_URI="https://www.freedesktop.org/software/${PN}/releases/${P}.tar.gz"
1802 +
1803 +LICENSE="LGPL-2"
1804 +SLOT="0"
1805 +KEYWORDS="amd64 x86"
1806 +IUSE="+elogind examples gtk +introspection kde nls pam selinux systemd test"
1807 +RESTRICT="!test? ( test )"
1808 +
1809 +REQUIRED_USE="^^ ( elogind systemd )"
1810 +
1811 +BDEPEND="
1812 + acct-user/polkitd
1813 + app-text/docbook-xml-dtd:4.1.2
1814 + app-text/docbook-xsl-stylesheets
1815 + dev-libs/glib
1816 + dev-libs/gobject-introspection-common
1817 + dev-libs/libxslt
1818 + dev-util/glib-utils
1819 + dev-util/gtk-doc-am
1820 + dev-util/intltool
1821 + sys-devel/gettext
1822 + virtual/pkgconfig
1823 + introspection? ( dev-libs/gobject-introspection )
1824 +"
1825 +DEPEND="
1826 + dev-lang/duktape
1827 + dev-libs/glib:2
1828 + dev-libs/expat
1829 + elogind? ( sys-auth/elogind )
1830 + pam? (
1831 + sys-auth/pambase
1832 + sys-libs/pam
1833 + )
1834 + systemd? ( sys-apps/systemd:0=[policykit] )
1835 +"
1836 +RDEPEND="${DEPEND}
1837 + acct-user/polkitd
1838 + selinux? ( sec-policy/selinux-policykit )
1839 +"
1840 +PDEPEND="
1841 + gtk? ( || (
1842 + >=gnome-extra/polkit-gnome-0.105
1843 + >=lxde-base/lxsession-0.5.2
1844 + ) )
1845 + kde? ( kde-plasma/polkit-kde-agent )
1846 +"
1847 +
1848 +DOCS=( docs/TODO HACKING NEWS README )
1849 +
1850 +PATCHES=(
1851 + "${FILESDIR}"/${PN}-${PV}-duktape.patch
1852 + "${FILESDIR}"/${PN}-${PV}-elogind.patch
1853 + "${FILESDIR}"/${PN}-${PV}-make-netgroup-support-optional.patch
1854 +)
1855 +
1856 +QA_MULTILIB_PATHS="
1857 + usr/lib/polkit-1/polkit-agent-helper-1
1858 + usr/lib/polkit-1/polkitd"
1859 +
1860 +src_prepare() {
1861 + default
1862 +
1863 + sed -i -e 's|unix-group:wheel|unix-user:0|' src/polkitbackend/*-default.rules || die #401513
1864 +
1865 + # Workaround upstream hack around standard gtk-doc behavior, bug #552170
1866 + sed -i -e 's/@ENABLE_GTK_DOC_TRUE@\(TARGET_DIR\)/\1/' \
1867 + -e '/install-data-local:/,/uninstall-local:/ s/@ENABLE_GTK_DOC_TRUE@//' \
1868 + -e 's/@ENABLE_GTK_DOC_FALSE@install-data-local://' \
1869 + docs/polkit/Makefile.in || die
1870 +
1871 + # disable broken test - bug #624022
1872 + sed -i -e "/^SUBDIRS/s/polkitbackend//" test/Makefile.am || die
1873 +
1874 + # Fix cross-building, bug #590764, elogind patch, bug #598615
1875 + eautoreconf
1876 +}
1877 +
1878 +src_configure() {
1879 + xdg_environment_reset
1880 +
1881 + local myeconfargs=(
1882 + --localstatedir="${EPREFIX}"/var
1883 + --disable-static
1884 + --enable-man-pages
1885 + --disable-gtk-doc
1886 + --disable-examples
1887 + --with-duktape
1888 + $(use_enable elogind libelogind)
1889 + $(use_enable introspection)
1890 + $(use_enable nls)
1891 + $(usex pam "--with-pam-module-dir=$(getpam_mod_dir)" '')
1892 + --with-authfw=$(usex pam pam shadow)
1893 + $(use_enable systemd libsystemd-login)
1894 + --with-systemdsystemunitdir="$(systemd_get_systemunitdir)"
1895 + $(use_enable test)
1896 + --with-os-type=gentoo
1897 + )
1898 + econf "${myeconfargs[@]}"
1899 +}
1900 +
1901 +src_compile() {
1902 + default
1903 +
1904 + # Required for polkitd on hardened/PaX due to spidermonkey's JIT
1905 + pax-mark mr src/polkitbackend/.libs/polkitd test/polkitbackend/.libs/polkitbackendjsauthoritytest
1906 +}
1907 +
1908 +src_install() {
1909 + default
1910 +
1911 + if use examples; then
1912 + docinto examples
1913 + dodoc src/examples/{*.c,*.policy*}
1914 + fi
1915 +
1916 + diropts -m 0700 -o polkitd
1917 + keepdir /usr/share/polkit-1/rules.d
1918 +
1919 + find "${ED}" -name '*.la' -delete || die
1920 +}
1921 +
1922 +pkg_postinst() {
1923 + chmod 0700 "${EROOT}"/{etc,usr/share}/polkit-1/rules.d
1924 + chown polkitd "${EROOT}"/{etc,usr/share}/polkit-1/rules.d
1925 +}