From 5f4697fd7d03aad17f5b5ee79a1fbc5f9b472601 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Tue, 8 Oct 2019 01:29:24 +0100 Subject: [PATCH] e - add polkit module to add an auth agent into e new feature - polkit auth agent support partly in core (need to have the pam setuid root auth tool respond via dbus) and partly a module (the agent dbus protocol handling and setup as well as auth gui). this took me a while even with all the docs to work out how polkit works... it was really fussy and its data structs are an extra pain in the butt to craft with eldbus, but i managed it. not everything is supported but the core basics are there and this can be built on. right now the gui is really basic, but does the job. --- data/config/default/e.src | 2 +- data/config/standard/e.src | 6 +- data/config/tiling/e.src | 7 +- meson_options.txt | 4 + src/bin/e_auth.c | 59 ++- src/bin/e_auth.h | 1 + src/bin/e_ckpasswd_main.c | 211 ++++++++-- src/bin/e_config.c | 27 ++ src/bin/e_config.h | 2 +- src/bin/e_module.c | 1 + src/bin/meson.build | 2 +- src/modules/meson.build | 1 + src/modules/polkit/auth_ui.c | 149 +++++++ src/modules/polkit/e-module-polkit.edj | Bin 0 -> 7523 bytes src/modules/polkit/e_mod_main.c | 17 + src/modules/polkit/e_mod_main.h | 32 ++ src/modules/polkit/meson.build | 6 + src/modules/polkit/module.desktop | 6 + src/modules/polkit/polkit.c | 523 +++++++++++++++++++++++++ 19 files changed, 1022 insertions(+), 34 deletions(-) create mode 100644 src/modules/polkit/auth_ui.c create mode 100644 src/modules/polkit/e-module-polkit.edj create mode 100644 src/modules/polkit/e_mod_main.c create mode 100644 src/modules/polkit/e_mod_main.h create mode 100644 src/modules/polkit/meson.build create mode 100644 src/modules/polkit/module.desktop create mode 100644 src/modules/polkit/polkit.c diff --git a/data/config/default/e.src b/data/config/default/e.src index a2e0e3e2e..a017effa9 100644 --- a/data/config/default/e.src +++ b/data/config/default/e.src @@ -1,5 +1,5 @@ group "E_Config" struct { - value "config_version" int: 1000028; + value "config_version" int: 1000029; value "config_type" uint: 0; // this profile seems to just be super minimalist value "show_splash" int: 0; value "desktop_default_name" string: "%i-%i"; diff --git a/data/config/standard/e.src b/data/config/standard/e.src index 4c716d877..bc9fc5dad 100644 --- a/data/config/standard/e.src +++ b/data/config/standard/e.src @@ -1,5 +1,5 @@ group "E_Config" struct { - value "config_version" int: 1000028; + value "config_version" int: 1000029; value "config_type" uint: 3; value "show_splash" int: 1; value "desktop_default_name" string: "%i-%i"; @@ -1015,6 +1015,10 @@ group "E_Config" struct { value "name" string: "bluez5"; value "enabled" uchar: 1; } + group "E_Config_Module" struct { + value "name" string: "polkit"; + value "enabled" uchar: 1; + } } group "xkb.used_layouts" list { group "E_Config_XKB_Layout" struct { diff --git a/data/config/tiling/e.src b/data/config/tiling/e.src index 431fce4bd..2d81e5a6d 100644 --- a/data/config/tiling/e.src +++ b/data/config/tiling/e.src @@ -1,5 +1,5 @@ group "E_Config" struct { - value "config_version" int: 1000028; + value "config_version" int: 1000029; value "config_type" uint: 3; value "show_splash" int: 1; value "desktop_default_name" string: "%i-%i"; @@ -1033,11 +1033,14 @@ group "E_Config" struct { value "name" string: "bluez5"; value "enabled" uchar: 1; } + group "E_Config_Module" struct { + value "name" string: "polkit"; + value "enabled" uchar: 1; + } group "E_Config_Module" struct { value "name" string: "tiling"; value "enabled" uchar: 1; } - } group "xkb.used_layouts" list { group "E_Config_XKB_Layout" struct { diff --git a/meson_options.txt b/meson_options.txt index d3457def8..3a077e8a7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -155,6 +155,10 @@ option('lokker', type: 'boolean', value: true, description: 'enable lokker module: (default=true)') +option('polkit', + type: 'boolean', + value: true, + description: 'enable polkit module: (default=true)') option('luncher', type: 'boolean', value: true, diff --git a/src/bin/e_auth.c b/src/bin/e_auth.c index 00b0e5d84..92670f5d3 100644 --- a/src/bin/e_auth.c +++ b/src/bin/e_auth.c @@ -6,14 +6,17 @@ e_auth_begin(char *passwd) char buf[PATH_MAX], *p; Ecore_Exe *exe = NULL; int ret = 0; + size_t pwlen; - if (strlen(passwd) == 0) goto out; + pwlen = strlen(passwd); + if (pwlen == 0) goto out; - snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_ckpasswd", + snprintf(buf, sizeof(buf), + "%s/enlightenment/utils/enlightenment_ckpasswd pw", e_prefix_lib_get()); - exe = ecore_exe_pipe_run(buf, ECORE_EXE_PIPE_WRITE, NULL); - if (ecore_exe_send(exe, passwd, strlen(passwd)) != EINA_TRUE) goto out; + if (!exe) goto out; + if (ecore_exe_send(exe, passwd, pwlen) != EINA_TRUE) goto out; ecore_exe_close_stdin(exe); ret = ecore_exe_pid_get(exe); @@ -24,12 +27,56 @@ e_auth_begin(char *passwd) } exe = NULL; + out: if (exe) ecore_exe_free(exe); /* security - null out passwd string once we are done with it */ for (p = passwd; *p; p++) *p = 0; - if (passwd[0] || passwd[3]) fprintf(stderr, "ACK!\n"); - + if (passwd[rand() % pwlen]) fprintf(stderr, "ACK!\n"); + return ret; +} + +E_API int +e_auth_polkit_begin(char *passwd, const char *cookie, unsigned int uid) +{ + char buf[PATH_MAX], *p; + Ecore_Exe *exe = NULL; + int ret = 0; + size_t pwlen, buflen = 0; + + pwlen = strlen(passwd); + if (pwlen == 0) goto out; + + snprintf(buf, sizeof(buf), + "%s/enlightenment/utils/enlightenment_ckpasswd pk", + e_prefix_lib_get()); + exe = ecore_exe_pipe_run(buf, ECORE_EXE_PIPE_WRITE, NULL); + if (!exe) goto out; + snprintf(buf, sizeof(buf), "%s %u %s", cookie, uid, passwd); + buflen = strlen(buf); + if (ecore_exe_send(exe, buf, buflen) != EINA_TRUE) goto out; + ecore_exe_close_stdin(exe); + + ret = ecore_exe_pid_get(exe); + if (ret == -1) + { + ret = 0; + goto out; + } + exe = NULL; + +out: + if (exe) ecore_exe_free(exe); + + /* security - null out passwd string once we are done with it */ + for (p = passwd; *p; p++) *p = 0; + if (passwd[rand() % pwlen]) fprintf(stderr, "ACK!\n"); + /* security - null out buf string once we are done with it */ + if (buflen > 0) + { + for (p = buf; *p; p++) *p = 0; + if (buf[rand() % buflen]) fprintf(stderr, "ACK!\n"); + } return ret; } diff --git a/src/bin/e_auth.h b/src/bin/e_auth.h index 2ca283763..8728f2900 100644 --- a/src/bin/e_auth.h +++ b/src/bin/e_auth.h @@ -2,6 +2,7 @@ #define E_AUTH_H E_API int e_auth_begin(char *passwd); +E_API int e_auth_polkit_begin(char *passwd, const char *cookie, unsigned int uid); static inline int e_auth_hash_djb2(const char *key, int len) diff --git a/src/bin/e_ckpasswd_main.c b/src/bin/e_ckpasswd_main.c index 31b04e738..173c5bd48 100644 --- a/src/bin/e_ckpasswd_main.c +++ b/src/bin/e_ckpasswd_main.c @@ -15,6 +15,10 @@ #include #endif +#include +#include +#include + #if defined(__OpenBSD__) static int @@ -162,42 +166,192 @@ _check_auth(uid_t uid, const char *pw) #endif +static int polkit_auth_ok = -1; + +static void +polkit_agent_response(void *data EINA_UNUSED, const Eldbus_Message *msg, + Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + + ecore_main_loop_quit(); + if (eldbus_message_error_get(msg, &name, &text)) + { + printf("Could not respond to auth.\n %s:\n %s\n", name, text); + return; + } + polkit_auth_ok = 0; + printf("Auth OK\n"); +} + +int +polkit_auth(const char *cookie, unsigned int auth_uid) +{ + Eldbus_Connection *c; + Eldbus_Object *obj; + Eldbus_Proxy *proxy; + Eldbus_Message *m; + Eldbus_Message_Iter *iter, *subj, *array, *dict, *vari; + unsigned int uid; + + eina_init(); + ecore_init(); + eldbus_init(); + c = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); + if (!c) return -1; + obj = eldbus_object_get(c, "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority"); + if (!obj) return -1; + proxy = eldbus_proxy_get(obj, "org.freedesktop.PolicyKit1.Authority"); + if (!proxy) return -1; + m = eldbus_proxy_method_call_new(proxy, "AuthenticationAgentResponse2"); + if (!m) return -1; + iter = eldbus_message_iter_get(m); + if (!iter) return -1; + uid = getuid(); + if (eldbus_message_iter_arguments_append(iter, "us", auth_uid, cookie)) + { + if (eldbus_message_iter_arguments_append(iter, "(sa{sv})", &subj)) + { + if (eldbus_message_iter_basic_append(subj, 's', "unix-user")) + { + if (eldbus_message_iter_arguments_append(subj, "a{sv}", &array)) + { + if (eldbus_message_iter_arguments_append(array, "{sv}", &dict)) + { + if (eldbus_message_iter_basic_append(dict, 's', "uid")) + { + vari = eldbus_message_iter_container_new(dict, 'v', "u"); + if (vari) + { + if (eldbus_message_iter_basic_append(vari, 'u', auth_uid)) + { + eldbus_message_iter_container_close(dict, vari); + } else return -1; + } else return -1; + } else return -1; + eldbus_message_iter_container_close(array, dict); + } else return -1; + eldbus_message_iter_container_close(subj, array); + } else return -1; + } else return -1; + eldbus_message_iter_container_close(iter, subj); + } else return -1; + eldbus_proxy_send(proxy, m, polkit_agent_response, NULL, -1); + } else return -1; + + ecore_main_loop_begin(); + + eldbus_connection_unref(c); + eldbus_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return polkit_auth_ok; +} + int main(int argc, char **argv) { ssize_t rd; uid_t id; char pw[4096], *p; + int polkit_mode = 0; + char polkit_cookie[4096]; + unsigned int polkit_uid = 0; - if (argc != 1) + if (argc < 2) { - int i; - - for (i = 1; i < argc; i++) - fprintf(stderr, "Unknown option %s\n", argv[i]); - fprintf(stderr, - "This is an internal tool for Enlightenment\n"); + fprintf(stderr, "This is an internal tool for Enlightenment\n"); + fprintf(stderr, "Options: pw | pk\n"); goto err; } + if (!strcmp(argv[1], "pw")) polkit_mode = 0; + else if (!strcmp(argv[1], "pk")) polkit_mode = 1; // get uid who ran this id = getuid(); // read passwd from stdin - rd = read(0, pw, sizeof(pw) - 1); - if (rd < 0) + if (polkit_mode == 0) { - fprintf(stderr, - "Error. Can't read passwd on stdin\n"); - goto err; - } - pw[rd] = 0; - for (p = pw; *p; p++) - { - if ((*p == '\r') || (*p == '\n')) + rd = read(0, pw, sizeof(pw) - 1); + if (rd < 0) { - *p = 0; - break; + fprintf(stderr, "Error. Can't read passwd on stdin\n"); + goto err; + } + pw[rd] = 0; + for (p = pw; *p; p++) + { + if ((*p == '\r') || (*p == '\n')) + { + *p = 0; + break; + } + } + } + else if (polkit_mode == 1) + { + unsigned int pos = 0; + + // read "cookie-string uid-string password...[\r|\n|EOF]" + for (;;) // cookie + { + rd = read(0, pw + pos, 1); + if (pw[pos] == ' ') + { + memcpy(polkit_cookie, pw, pos); + polkit_cookie[pos] = 0; + printf("COOKIE: [%s]\n", polkit_cookie); + pos = 0; + break; + } + else + { + pos++; + if (pos > 4000) + { + fprintf(stderr, "Error. Polkit cookie too long\n"); + return -10; + } + } + } + for (;;) // uid + { + rd = read(0, pw + pos, 1); + if (pw[pos] == ' ') + { + pw[pos] = 0; + polkit_uid = atoi(pw); + printf("UID: [%u]\n", polkit_uid); + break; + } + else + { + pos++; + if (pos > 4000) + { + fprintf(stderr, "Error. Polkit uid too long\n"); + return -11; + } + } + } + // password + printf("READPASS...\n"); + rd = read(0, pw, sizeof(pw) - 1); + if (rd < 0) + { + fprintf(stderr, "Error. Can't read passwd on stdin\n"); + goto err; + } + pw[rd] = 0; + for (p = pw; *p; p++) + { + if ((*p == '\r') || (*p == '\n')) + { + *p = 0; + break; + } } } @@ -209,9 +363,22 @@ main(int argc, char **argv) if (setgid(0) != 0) fprintf(stderr, "Warning. Can't become group root. If password auth requires root then this will fail\n"); - if (_check_auth(id, pw) == 0) return 0; + if (_check_auth(id, pw) == 0) + { + fprintf(stderr, "Password OK\n"); + if (polkit_mode == 1) + { + if (polkit_auth(polkit_cookie, polkit_uid) == 0) + { + fprintf(stderr, "Polkit AuthenticationAgentResponse2 success\n"); + return 0; + } + fprintf(stderr, "Polkit AuthenticationAgentResponse2 failure\n"); + return -2; + } + return 0; + } err: - fprintf(stderr, - "Password auth fail\n"); + fprintf(stderr, "Password auth fail\n"); return -1; } diff --git a/src/bin/e_config.c b/src/bin/e_config.c index 5195321a1..00fe41138 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -1441,6 +1441,7 @@ e_config_load(void) e_config->window_maximize_animate = 1; e_config->window_maximize_transition = E_EFX_EFFECT_SPEED_SINUSOIDAL; e_config->window_maximize_time = 0.15; + e_config_save_queue(); } CONFIG_VERSION_CHECK(22) { @@ -1465,6 +1466,7 @@ e_config_load(void) module->enabled = 1; e_config->modules = eina_list_append(e_config->modules, module); } + e_config_save_queue(); } CONFIG_VERSION_CHECK(23) { @@ -1487,6 +1489,7 @@ e_config_load(void) module->enabled = 1; e_config->modules = eina_list_append(e_config->modules, module); } + e_config_save_queue(); } CONFIG_VERSION_CHECK(24) { @@ -1494,6 +1497,7 @@ e_config_load(void) if (!elm_config_profile_exists(_e_config_profile)) elm_config_profile_save(_e_config_profile); + e_config_save_queue(); } CONFIG_VERSION_CHECK(25) { @@ -1574,6 +1578,29 @@ e_config_load(void) } e_config_save_queue(); } + CONFIG_VERSION_CHECK(29) + { + Eina_List *l; + E_Config_Module *em, *module; + Eina_Bool mod_loaded = EINA_FALSE; + + CONFIG_VERSION_UPDATE_INFO(29); + + EINA_LIST_FOREACH(e_config->modules, l, em) + { + if (!em->enabled) continue; + if (eina_streq(em->name, "polkit")) + mod_loaded = EINA_TRUE; + } + if (!mod_loaded) + { + module = E_NEW(E_Config_Module, 1); + module->name = eina_stringshare_add("polkit"); + module->enabled = 1; + e_config->modules = eina_list_append(e_config->modules, module); + } + e_config_save_queue(); + } } elm_config_profile_set(_e_config_profile); if (!e_config->remember_internal_fm_windows) diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 0c732502c..3eeb395fb 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -46,7 +46,7 @@ typedef enum /* increment this whenever a new set of config values are added but the users * config doesn't need to be wiped - simply new values need to be put in */ -#define E_CONFIG_FILE_GENERATION 28 +#define E_CONFIG_FILE_GENERATION 29 #define E_CONFIG_FILE_VERSION ((E_CONFIG_FILE_EPOCH * 1000000) + E_CONFIG_FILE_GENERATION) #define E_CONFIG_BINDINGS_VERSION 0 // DO NOT INCREMENT UNLESS YOU WANT TO WIPE ALL BINDINGS!!!!! diff --git a/src/bin/e_module.c b/src/bin/e_module.c index bcc824e7d..92176625e 100644 --- a/src/bin/e_module.c +++ b/src/bin/e_module.c @@ -753,6 +753,7 @@ _e_module_whitelist_check(void) "ibox", "layout", "lokker", + "polkit", "luncher", "mixer", "msgbus", diff --git a/src/bin/meson.build b/src/bin/meson.build index 138bb6596..4a0878eb9 100644 --- a/src/bin/meson.build +++ b/src/bin/meson.build @@ -34,7 +34,7 @@ deps_e = [ dep_intl ] -deps_ckpass = [ ] +deps_ckpass = [ dep_eina, dep_ecore, dep_eldbus ] if freebsd == true deps_ckpass += dep_crypt diff --git a/src/modules/meson.build b/src/modules/meson.build index 5ace236b3..a244bd320 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -65,6 +65,7 @@ mods = [ # also standard modules with no icon or desktop file 'xwayland', 'lokker', + 'polkit', 'wl_x11', 'wl_wl', 'wl_buffer', diff --git a/src/modules/polkit/auth_ui.c b/src/modules/polkit/auth_ui.c new file mode 100644 index 000000000..88639ebf4 --- /dev/null +++ b/src/modules/polkit/auth_ui.c @@ -0,0 +1,149 @@ +#include "e_mod_main.h" + +static Eina_Bool +_auth_cb_exit(void *data, int type EINA_UNUSED, void *event) +{ + Polkit_Session *ps = data; + Ecore_Exe_Event_Del *ev = event; + + if (ev->pid != ps->auth_pid) return ECORE_CALLBACK_PASS_ON; + ps->auth_pid = 0; + if (ps->exe_exit_handler) ecore_event_handler_del(ps->exe_exit_handler); + ps->exe_exit_handler = NULL; + session_reply(ps); + return ECORE_CALLBACK_PASS_ON; +} + +static void +_cb_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + Polkit_Session *ps = evas_object_data_get(obj, "session"); + if (!ps) return; + if (ps->exe_exit_handler) + { + ecore_event_handler_del(ps->exe_exit_handler); + ps->exe_exit_handler = NULL; + } + if (ps->win) + { + ps->win = NULL; + session_reply(ps); + } +} + +static void +_cb_ok(void *data EINA_UNUSED, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + Polkit_Session *ps = evas_object_data_get(obj, "session"); + const char *str = elm_object_text_get(obj); + + if (!ps) return; + if (ps->exe_exit_handler) return; + ps->exe_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _auth_cb_exit, ps); + if (str) + { + char *passwd = strdup(str); + if (passwd) + { + ps->auth_pid = e_auth_polkit_begin(passwd, ps->cookie, ps->target_uid); + free(passwd); + return; + } + } + evas_object_del(ps->win); +} + +static void +_cb_cancel(void *data EINA_UNUSED, Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + Polkit_Session *ps = evas_object_data_get(obj, "session"); + if (!ps) return; + if (ps->exe_exit_handler) return; + session_reply(ps); +} + +static void +_cb_button_ok(void *data, E_Dialog *dia EINA_UNUSED) +{ + _cb_ok(NULL, data, NULL); +} + +static void +_cb_button_cancel(void *data, E_Dialog *dia EINA_UNUSED) +{ + _cb_cancel(NULL, data, NULL); +} + +void +auth_ui(Polkit_Session *ps) +{ + E_Dialog *dia; + Evas_Object *o, *win, *box, *ent; + + dia = e_dialog_new(NULL, "E", "_polkit_auth"); + e_dialog_title_set(dia, _("Please enter password")); + + win = dia->win; + + if ((!ps->icon_name) || (!ps->icon_name[0])) + e_dialog_icon_set(dia, "enlightenment", 64); + else + e_dialog_icon_set(dia, ps->icon_name, 64); + + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cb_del, NULL); + elm_win_autodel_set(win, EINA_TRUE); + evas_object_data_set(win, "session", ps); + + box = o = elm_box_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, -1.0, -1.0); + elm_box_horizontal_set(o, EINA_FALSE); + e_dialog_content_set(dia, o, 0, 0); + evas_object_show(o); + +/* XXX: lookup action and display something useful for it in future. + o = elm_label_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.0); + elm_object_text_set(o, ps->action); + elm_box_pack_end(box, o); + evas_object_show(o); + */ + + o = elm_label_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, 0.0, 0.0); + elm_object_text_set(o, ps->message); + elm_box_pack_end(box, o); + evas_object_show(o); + + ent = o = elm_entry_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, -1.0, 1.0); + elm_entry_single_line_set(ent, EINA_TRUE); + elm_entry_scrollable_set(ent, EINA_TRUE); + elm_entry_password_set(ent, EINA_TRUE); + elm_object_part_text_set(ent, "elm.guide", "Enter Password"); + evas_object_data_set(ent, "session", ps); + evas_object_smart_callback_add(ent, "activated", _cb_ok, NULL); + evas_object_smart_callback_add(ent, "aborted", _cb_cancel, NULL); + elm_box_pack_end(box, o); + evas_object_show(o); + + e_dialog_button_add(dia, _("OK"), NULL, _cb_button_ok, ent); + e_dialog_button_add(dia, _("Cancel"), NULL, _cb_button_cancel, ent); + e_dialog_button_focus_num(dia, 0); + + elm_object_focus_set(ent, EINA_TRUE); + + ps->win = win; + ps->entry = ent; + + elm_win_center(win, 1, 1); + e_dialog_show(dia); + elm_win_activate(win); +} diff --git a/src/modules/polkit/e-module-polkit.edj b/src/modules/polkit/e-module-polkit.edj new file mode 100644 index 0000000000000000000000000000000000000000..807f83df4830a28de5fdd24882f15fcbcd99f01f GIT binary patch literal 7523 zcmZvg2Ut^A8^^D>s0$DQ`?&yDtu`puT3i?)q6NX?o-rgBh=wHQh7l^Rx@)Q8-Ysgy z-C8YbRTQw;I_jua0jov%aN_{Qit_#6o80sy{qFOeyyyJRd(U{+McbCUg>W2KAMFQ@ z^I6DoF7H@dvsqxx(D1yw20u-#tyuSjz!Fq$S=X(Vf3dWvgF<2xRyYCCI5l-w0*aR@v z_OOFnEHO06&eOmWoY*WdJu${s!C+=E(Wb=F$9dg8BgW{ZgUxYbC&3nhu|CQJTj9h~ zz&3+5W7fm{-S&XFGb|kJ7%?>I9<#yDVJOBn>7u_3tk{VmPTlT-QS3_Z!e4IBomhJ? ziXnE7&KOcIuxI%T!!}^-nV*7nC59&Lp#}@Wun}_)_`)6cb2y6|*ibOmR`9p`7^in} ze|Nm^5C^!I`xIi#9=L-Y`39#m9^pJib7}W?*MsE)o>WPD`c7s(AWAsp$+>tj946)$> zzgy!JvK<=Y)`MbzwR0UXFEBASAX}iF2P1v<9{s^kPpk}*@(JhjApbT-qla?&1F$ei zc8{%K(O~R)zkpG$vblc{jPlY0O|qXKhOn1|?SsL{Z=ww#ebCNmHC4hrVDTkRHstzk&^SVhg}DVC;Hbz{pnOnIT=!{J}CH+4XR* z=9?u38Gv>j>^n#{&zFOp0BcQWfh0c{fR#Y9b#gpdDOg?R%=5q~cG)=C14gzI_ke^S zIr!WY!s>HKstx!idQuFCab??k2N=G44(H1OqnKpxhB)wq->r6m9E1j2dB#ABK7yqF zXs`rGHsA0q^F)qt^=*4LK_A~4&smTS(deO^Z3Bii9df!om{{9M2@l2`#-3znwkDzm zdBP6%Jfb)F(2~I@_gOpBzKB7)9&|YP zsKp6}QJkPAwjkR}u|Y9*3G9NzY%vo8b_I;iD)|ll7G)T+XTAl7*m7XsA#5qm*c?O* zdHIkY8a?r7i^0er-URT_+%hn#Z&L32qR(SUb%Xpaodr5xWPA2|N$X7plkPST{YGGT z-=SvHdWbjsw}NuO1&sV5t_SIlhW)(eLW(|zoQekDdXbMLJv#qFu$7Q(ErBn*sAh}t z2RQ+4BiMFG*1zY#4oeJjG8*#1i+sfTcN*ALFjq8sywI*e{0Yg%j*~i&wf8%fPDleeYdE7j{qA8$(|W8067K;&4B2_{qUmsB7LujNTOVmP1T_3f7z$llwtn?Z8-@W`Mm9#@_8F82O_k^Dg4WhwLo=Z3~IJiu-CIC0p%6 ze-rdz*MDjvubILJXcJZOyb#cxqmfcDB$?E_GR~kkC#sAr6U0G4oL0wMduoGD$E(d+ zgPz_ts!V2q6Bpz3szjdC@Nudnomr{j1+_Hb1hdM_%f$KasojlTyW2>zN|(fQ$yz}h zi{&vT`*PF2) z>82SBiB5==Qtj#%doNAw8T6tM5)B43Im;+h>5K{1jm2G+HjP-7da61}rxSI=ZLEum zT?;4b%F>KFm7cc^;tXn)jR^!BmZkff)q zu>;FLT~U`ATXmg4oL0|M#R~{PVXCcbbuEg7T8mW>V_LnS)$kmxsnQ`S^eA~^ zK~*O5W|LMea7KfcvPGF_fF4d{vRJzUPX*Q5S0|YSgH0t7byTav6*-k!%?kpj=V28j zU4mApL8dE3o8Y|DlC&m-w^$&_FVar`5alrI-kgApMY-3e@v;=H26@MT1YS&Uqsd^T znuywI?ye(u1d9N(D0w}_i3TST--bnD1A2o@sZJ8ihD4=69-;4tz}zX+{v|^B$M-`psYR*N z3TA1b6bJNOv-ZTVom!2;muSR0CN3HEjW)xD4JIxQ`y|2Lpd25kBT2KeMAa0`IuKDm zR)sTKLxCKs#reo2GNV4;>S50IWfcR@)`z`RiPn3FNuvyd`_yIw;z2=C@qeeRg+Qs% zibdP@1;#ayL9!S{=m>dKc%;HM9-$aB!qy!!R30wjVKLET#@hJs(elX1=+VpzA(7Fc z5w>x7O!UZMwth(T7)eVWV&4KgC}N`Ik+!Mf!{nig7-Ua*}RvwI+V)bK~9^*`4jr6;xMQBiJJg{pPowA`|sn)mtT@-EBe``4^!r|8m{ z|DngYmMa674q1D4(C5J?G~Ta{4QsiggWuklDW9bsd0E=0_iz1QJ};_x-mgOV&2s+m z#__{^{WB*j?w)G&V%is@kKS(Ea7;e;iO1^4foE?wSkx}XsGs}ym3?B@uTrUY>Gj>q z^erEU45-|ko>&wUL?knhAT4Ja$4?m~+OkR>(J7nuR zb(3ioxgnl4PaphMJJWaX%iz8ZP8kb>2My?7TU}fJ>}KK)?DI!OJ9fX?=-h>aOQzSk z?b?$55kybu;0R4UNNJo}#D6t(YJT@7^N+R3pFC53r{S81>q@*^&JH}1|M=9kDc!3Z z7hm6Y=ex@TW>jf%w%mB%JqX5bzsWQ%Fx)lW|EAUXe)IA=Y-v{3XnYb z6tZ<-bmfy1KV|0sa&6wi&z9WnkeFI>JZkjkRlbj>AIO_9 zYW#U!lz4GSqr8Fc^)Fy72o)BTC}Mu?aj$LWr^!>Z zd*<%TiW;e0RsQ$M{$*JPi|ngD7ys-V)}ZL9$GLXPBSO-RinNT>^KiHY;dS zb^n3ai64>*JFmu-RF1iQ18P=i(6&uN?l6lxS#m4m&?VkeOTf6D;rsZS$EjxSXy@PvKEI#GA zV?tT~I%jJ0+D;96HTsNl&(R%a0i*uB@GL$$qh)Qk@?h1+t{dL5=xW|3yy{ZTKk$0? zv2M)vZFy}QE;(Q0{bXgssy^J$9)baBp{{8e-ho@ck2bjC9-Eei6YxNR!m%_2b$0^4?oYHYZ>6kgIFU9c% zWh+X83Y+hnlNnSo=3&6nT19C@!ODV>8QU(c{{G>WLHF{#=I(O+!+o!M)_>-9UpZ#mp;@=gmJ0Fie+19tilO{LJXWEs1Ff&YD5}LAgb+ei^mFahC=T^SC z6MU;O^X%7iDy}Vkosl@N+v|+q?$*3M_d{5E#;W`~K_Oj^4lIiZoS~>$*Qv7U)AzPj zU7ZnHFZ0@#6xS}T3wxA2>EE$?RQl$DgWE^?NBTv!KkIwefBL}ch20lC8S>~xr+c-% zk9>1eJ88y+r~h5#vv6jgRk;Tg$7aX_b1$YYnsRW-$Vu{Z@8_+XT|4vUlP&)PLfG-a literal 0 HcmV?d00001 diff --git a/src/modules/polkit/e_mod_main.c b/src/modules/polkit/e_mod_main.c new file mode 100644 index 000000000..c7cc07a55 --- /dev/null +++ b/src/modules/polkit/e_mod_main.c @@ -0,0 +1,17 @@ +#include "e_mod_main.h" + +E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Polkit"}; + +E_API void * +e_modapi_init(E_Module *m) +{ + e_mod_polkit_register(); + return m; +} + +E_API int +e_modapi_shutdown(E_Module *m EINA_UNUSED) +{ + e_mod_polkit_unregister(); + return 1; +} diff --git a/src/modules/polkit/e_mod_main.h b/src/modules/polkit/e_mod_main.h new file mode 100644 index 000000000..db38fa9c2 --- /dev/null +++ b/src/modules/polkit/e_mod_main.h @@ -0,0 +1,32 @@ +#ifndef E_MOD_MAIN_H +#define E_MOD_MAIN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "e.h" + +typedef struct +{ + const char *cookie; + const char *message; + const char *icon_name; + const char *action; + unsigned int target_uid; + int auth_pid; + Ecore_Event_Handler *exe_exit_handler; + Eldbus_Message *reply; + Eldbus_Pending *pend_reply; + Evas_Object *win; + Evas_Object *entry; +} Polkit_Session; + +void session_reply(Polkit_Session *ps); + +void auth_ui(Polkit_Session *ps); + +void e_mod_polkit_register(void); +void e_mod_polkit_unregister(void); + +#endif diff --git a/src/modules/polkit/meson.build b/src/modules/polkit/meson.build new file mode 100644 index 000000000..f839f7aa1 --- /dev/null +++ b/src/modules/polkit/meson.build @@ -0,0 +1,6 @@ +src = files( + 'e_mod_main.c', + 'polkit.c', + 'auth_ui.c', + 'e_mod_main.h' + ) diff --git a/src/modules/polkit/module.desktop b/src/modules/polkit/module.desktop new file mode 100644 index 000000000..f1189282c --- /dev/null +++ b/src/modules/polkit/module.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Link +Name=Polkit +Comment=This module provides a polkit authentication agent +Icon=e-module-polkit +X-Enlightenment-ModuleType=core diff --git a/src/modules/polkit/polkit.c b/src/modules/polkit/polkit.c new file mode 100644 index 000000000..d29b8547e --- /dev/null +++ b/src/modules/polkit/polkit.c @@ -0,0 +1,523 @@ +#include "e_mod_main.h" + +static Eldbus_Connection *pk_conn = NULL; +static Eldbus_Service_Interface *agent_iface = NULL; +static Eldbus_Object *pk_obj = NULL; +static Eldbus_Proxy *pk_proxy = NULL; + +static Eldbus_Pending *pend_call = NULL; + +static Eldbus_Object *ses_obj = NULL; +static Eldbus_Object *ses_obj2 = NULL; +static Eldbus_Proxy *ses_proxy = NULL; +static Eldbus_Proxy *ses_proxy2 = NULL; + +static Eina_Bool agent_request = EINA_FALSE; +static Eina_Bool agent_ok = EINA_FALSE; +static const char *session_path = NULL; +static const char *session_id = NULL; +static unsigned int session_uid = 0; +static const char *session_user = NULL; + +////////////////////////////////////////////////////////////////////////////// + +static Eina_Hash *sessions = NULL; + +static void +_session_free(Polkit_Session *ps) +{ + if (ps->reply) eldbus_connection_send(pk_conn, ps->reply, NULL, NULL, -1); + ps->reply = NULL; + if (ps->pend_reply) eldbus_pending_cancel(ps->pend_reply); + ps->pend_reply = NULL; + eina_stringshare_del(ps->cookie); + ps->cookie = NULL; + eina_stringshare_del(ps->message); + ps->message = NULL; + eina_stringshare_del(ps->icon_name); + ps->icon_name = NULL; + eina_stringshare_del(ps->action); + ps->action = NULL; + if (ps->win) + { + Evas_Object *win = ps->win; + + ps->win = NULL; + evas_object_del(win); + } + free(ps); +} + +static void +session_init(void) +{ + if (sessions) return; + sessions = eina_hash_string_superfast_new((void *)_session_free); +} + +static void +session_shutdown(void) +{ + if (sessions) eina_hash_free(sessions); + sessions = NULL; +} + +static Polkit_Session * +session_new(void) +{ + return calloc(1, sizeof(Polkit_Session)); +} + +static void +session_free(Polkit_Session *ps) +{ + eina_hash_del(sessions, ps->cookie, ps); +} + +static void +session_register(Polkit_Session *ps) +{ + eina_hash_add(sessions, ps->cookie, ps); +} + +static Polkit_Session * +session_find(const char *cookie) +{ + return eina_hash_find(sessions, cookie); +} + +void +session_reply(Polkit_Session *ps) +{ + if (ps->reply) + { + ps->pend_reply = eldbus_connection_send(pk_conn, ps->reply, NULL, NULL, -1); + ps->reply = NULL; + } + session_free(ps); +} + +void +session_show(Polkit_Session *ps) +{ + auth_ui(ps); + // display some auth dialog to enter a password, show ps->message + // and ps->action specific ui ps->icon_name + // when we get the password call + // e_auth_polkit_begin(pass, ps->cookie, ps->target_uid); + // when this returns call session_reply(ps); +} + +////////////////////////////////////////////////////////////////////////////// + +static void +iterate_dict(void *data, const void *key, Eldbus_Message_Iter *var) +{ + Polkit_Session *ps = data; + const char *skey = key; + + if (!strcmp(skey, "uid")) + { + unsigned int uid = 0; + + if (eldbus_message_iter_arguments_get(var, "u", &uid)) + ps->target_uid = uid; + } +} + +static Eldbus_Message * +cb_agent_begin_authentication(const Eldbus_Service_Interface *iface EINA_UNUSED, + const Eldbus_Message *msg) +{ + // sssa{ss}sa(sa{sv}) + const char *action_id = NULL, *message = NULL, *icon_name = NULL, + *cookie = NULL; + Eldbus_Message_Iter *details = NULL, *ident = NULL, *item = NULL; + Polkit_Session *ps, *ps2; + + ps = session_new(); + if (!ps) goto err; + ps->reply = eldbus_message_method_return_new(msg); + + if (!eldbus_message_arguments_get(msg, "sssa{ss}sa(sa{sv})", + &action_id, &message, &icon_name, + &details, &cookie, &ident)) + goto err; + ps->cookie = eina_stringshare_add(cookie); + ps->message = eina_stringshare_add(message); + ps->icon_name = eina_stringshare_add(icon_name); + ps->action = eina_stringshare_add(action_id); + // actions in: /usr/share/polkit-1/actions + +/* XXX: Haven't seen details content yet - not sure what to do with it + while (eldbus_message_iter_get_and_next(details, 'r', &item)) + { + const char *v1, *v2; + + v1 = NULL; + v2 = NULL; + eldbus_message_iter_arguments_get(item, "ss", &v1, &v2); + } + */ + while (eldbus_message_iter_get_and_next(ident, 'r', &item)) + { + const char *v1; + Eldbus_Message_Iter *dict = NULL; + + v1 = NULL; + eldbus_message_iter_arguments_get(item, "sa{sv}", &v1, &dict); + if (!strcmp(v1, "unix-user")) + eldbus_message_iter_dict_iterate(dict, "sv", iterate_dict, ps); + else + { + printf("PK: Unhandled ident type.\n"); + } + } + ps2 = session_find(ps->cookie); + if (ps2) session_free(ps2); + session_register(ps); + session_show(ps); + return NULL; +err: + return eldbus_message_method_return_new(msg); +} + +static Eldbus_Message * +cb_agent_cancel_authentication(const Eldbus_Service_Interface *iface EINA_UNUSED, + const Eldbus_Message *msg) +{ + const char *cookie; + Polkit_Session *ps; + + // s + if (!eldbus_message_arguments_get(msg, "s", &cookie)) return NULL; + ps = session_find(cookie); + if (ps) session_free(ps); + return eldbus_message_method_return_new(msg); +} + +////////////////////////////////////////////////////////////////////////////// + +static void +cb_register(void *data EINA_UNUSED, const Eldbus_Message *msg, + Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + + pend_call = NULL; + if (eldbus_message_error_get(msg, &name, &text)) return; + agent_request = EINA_FALSE; + agent_ok = EINA_TRUE; +} + +static const Eldbus_Method agent_methods[] = { + { "BeginAuthentication", + ELDBUS_ARGS({ "s", "action_id" }, + { "s", "message" }, + { "s", "icon_name" }, + { "a{ss}", "details" }, + { "s", "cookie" }, + { "a(sa{sv})", "identities" }), + NULL, + cb_agent_begin_authentication, 0 + }, + { "CancelAuthentication", + ELDBUS_ARGS({ "s", "cookie" }), + NULL, + cb_agent_cancel_authentication, 0 + }, + { NULL, NULL, NULL, NULL, 0 } +}; +static const Eldbus_Service_Interface_Desc agent_desc = { + "org.freedesktop.PolicyKit1.AuthenticationAgent", agent_methods, NULL, NULL, NULL, NULL +}; + +static void +pk_agent_register(void) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *iter, *subj, *array, *dict, *vari; + const char *locale = NULL; + + agent_request = EINA_TRUE; + // set up agent interface + agent_iface = eldbus_service_interface_register + (pk_conn, "/org/enlightenment/polkit/Agent", &agent_desc); + + // register agent interface with polkit + if (!locale) locale = getenv("LC_MESSAGES"); + if (!locale) locale = getenv("LC_ALL"); + if (!locale) locale = getenv("LANG"); + if (!locale) locale = getenv("LANGUAGE"); + if (!locale) locale = "C"; + + pk_obj = eldbus_object_get(pk_conn, "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority"); + if (!pk_obj) return; + pk_proxy = eldbus_proxy_get(pk_obj, "org.freedesktop.PolicyKit1.Authority"); + if (!pk_proxy) return; + msg = eldbus_proxy_method_call_new(pk_proxy, "RegisterAuthenticationAgent"); + // (sa{sv})ss + iter = eldbus_message_iter_get(msg); + eldbus_message_iter_arguments_append(iter, "(sa{sv})", &subj); + eldbus_message_iter_basic_append(subj, 's', "unix-session"); + eldbus_message_iter_arguments_append(subj, "a{sv}", &array); + eldbus_message_iter_arguments_append(array, "{sv}", &dict); + eldbus_message_iter_basic_append(dict, 's', "session-id"); + vari = eldbus_message_iter_container_new(dict, 'v', "s"); + eldbus_message_iter_basic_append(vari, 's', session_id); + eldbus_message_iter_container_close(dict, vari); + eldbus_message_iter_container_close(array, dict); + eldbus_message_iter_container_close(subj, array); + eldbus_message_iter_container_close(iter, subj); + + eldbus_message_iter_basic_append(iter, 's', locale); + eldbus_message_iter_basic_append(iter, 's', "/org/enlightenment/polkit/Agent"); + pend_call = eldbus_proxy_send(pk_proxy, msg, cb_register, NULL, -1); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void +cb_login_prop_entry(void *data EINA_UNUSED, const void *key, Eldbus_Message_Iter *var) +{ + const char *skey = key; + + if (!strcmp(skey, "Id")) + { + const char *val = NULL; + if (eldbus_message_iter_arguments_get(var, "s", &val)) + eina_stringshare_replace(&session_id, val); + } + else if (!strcmp(skey, "User")) + { + Eldbus_Message_Iter *iter = NULL; + + eldbus_message_iter_arguments_get(var, "(uo)", &iter); + if (iter) + { + unsigned int uid = 0; + const char *val = NULL; + + if (eldbus_message_iter_arguments_get(iter, "uo", &uid, &val)) + { + session_uid = uid; + eina_stringshare_replace(&session_user, val); + } + } + } +} + +static void +cb_login_prop(void *data EINA_UNUSED, const Eldbus_Message *msg, + Eldbus_Pending *pending EINA_UNUSED) +{ + Eldbus_Message_Iter *array; + + pend_call = NULL; + if (eldbus_message_error_get(msg, NULL, NULL)) return; + if (eldbus_message_arguments_get(msg, "a{sv}", &array)) + { + eldbus_message_iter_dict_iterate(array, "sv", + cb_login_prop_entry, NULL); + if ((session_id) && (session_user) && (session_path)) + pk_agent_register(); + } + if (ses_proxy2) eldbus_proxy_unref(ses_proxy2); + ses_proxy2 = NULL; + if (ses_proxy) eldbus_proxy_unref(ses_proxy); + ses_proxy = NULL; + if (ses_obj) eldbus_object_unref(ses_obj); + ses_obj = NULL; + if (ses_obj2) eldbus_object_unref(ses_obj2); + ses_obj2 = NULL; +} + +static void +cb_login_session(void *data EINA_UNUSED, const Eldbus_Message *msg, + Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + const char *s; + + pend_call = NULL; + if (eldbus_message_error_get(msg, &name, &text)) return; + if (!eldbus_message_arguments_get(msg, "o", &s)) return; + eina_stringshare_replace(&session_path, s); + ses_obj2 = eldbus_object_get(pk_conn, "org.freedesktop.login1", s); + if (!ses_obj2) return; + ses_proxy2 = eldbus_proxy_get(ses_obj2, "org.freedesktop.login1.Session"); + if (!ses_proxy2) return; + pend_call = eldbus_proxy_property_get_all(ses_proxy2, cb_login_prop, NULL); +} + +static void +pk_session_init(void) +{ + ses_obj = eldbus_object_get(pk_conn, "org.freedesktop.login1", + "/org/freedesktop/login1"); + if (!ses_obj) return; + ses_proxy = eldbus_proxy_get(ses_obj, "org.freedesktop.login1.Manager"); + if (!ses_proxy) return; + pend_call = eldbus_proxy_call(ses_proxy, "GetSessionByPID", + cb_login_session, NULL, -1, + "u", (unsigned int)getpid()); +} + +///////////////////////////////////////////////////////////////////////////// + +static Ecore_Timer *owner_gain_timer = NULL; + +static Eina_Bool +cb_name_owner_new(void *data EINA_UNUSED) +{ + owner_gain_timer = NULL; + pk_session_init(); + session_init(); + return EINA_FALSE; +} + +static void +cb_name_owner_changed(void *data EINA_UNUSED, + const char *bus EINA_UNUSED, + const char *from EINA_UNUSED, + const char *to) +{ + static Eina_Bool first = EINA_TRUE; + + if (to[0]) + { + if (owner_gain_timer) ecore_timer_del(owner_gain_timer); + // on first start try and re-init quickly because we get a name + // owner change even if all is good when we register to listen for it, + // so start fast + if (first) + owner_gain_timer = ecore_timer_add(0.1, cb_name_owner_new, NULL); + // but if we gegt a name owner change later it's probably because + // bluez was restarted or crashed. a new bz daemon will (or should) + // come up. so re-init more slowly here giving the daemon some time + // to come up before pestering it. + else + owner_gain_timer = ecore_timer_add(1.0, cb_name_owner_new, NULL); + first = EINA_FALSE; + } + else + { + session_shutdown(); + if (pend_call) eldbus_pending_cancel(pend_call); + pend_call = NULL; + if (agent_iface) eldbus_service_object_unregister(agent_iface); + agent_iface = NULL; + if (owner_gain_timer) ecore_timer_del(owner_gain_timer); + owner_gain_timer = NULL; + + if (pk_proxy) eldbus_proxy_unref(pk_proxy); + pk_proxy = NULL; + if (pk_obj) eldbus_object_unref(pk_obj); + pk_obj = NULL; + + if (pk_proxy) eldbus_proxy_unref(pk_proxy); + pk_proxy = NULL; + if (pk_obj) eldbus_object_unref(pk_obj); + pk_obj = NULL; + if (ses_proxy2) eldbus_proxy_unref(ses_proxy2); + ses_proxy2 = NULL; + if (ses_proxy) eldbus_proxy_unref(ses_proxy); + ses_proxy = NULL; + if (ses_obj) eldbus_object_unref(ses_obj); + ses_obj = NULL; + if (ses_obj2) eldbus_object_unref(ses_obj2); + ses_obj2 = NULL; + agent_request = EINA_FALSE; + agent_ok = EINA_FALSE; + eina_stringshare_replace(&session_path, NULL); + eina_stringshare_replace(&session_id, NULL); + eina_stringshare_replace(&session_user, NULL); + session_uid = 0; + } +} + +void +e_mod_polkit_register(void) +{ + agent_request = EINA_FALSE; + agent_ok = EINA_FALSE; + pk_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); + if (pk_conn) + { + eldbus_name_owner_changed_callback_add(pk_conn, + "org.freedesktop.PolicyKit1", + cb_name_owner_changed, NULL, + EINA_TRUE); + } +} + +void +e_mod_polkit_unregister(void) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *iter, *subj, *array, *dict, *vari; + + if (!pk_conn) return; + eldbus_name_owner_changed_callback_del(pk_conn, + "org.freedesktop.PolicyKit1", + cb_name_owner_changed, NULL); + if (pend_call) eldbus_pending_cancel(pend_call); + pend_call = NULL; + + if ((agent_request || agent_ok) && (session_id) && (pk_proxy)) + { + msg = eldbus_proxy_method_call_new(pk_proxy, + "UnregisterAuthenticationAgent"); + // (sa{sv})s + iter = eldbus_message_iter_get(msg); + eldbus_message_iter_arguments_append(iter, "(sa{sv})", &subj); + eldbus_message_iter_basic_append(subj, 's', "unix-session"); + eldbus_message_iter_arguments_append(subj, "a{sv}", &array); + eldbus_message_iter_arguments_append(array, "{sv}", &dict); + eldbus_message_iter_basic_append(dict, 's', "session-id"); + vari = eldbus_message_iter_container_new(dict, 'v', "s"); + eldbus_message_iter_basic_append(vari, 's', session_id); + eldbus_message_iter_container_close(dict, vari); + eldbus_message_iter_container_close(array, dict); + eldbus_message_iter_container_close(subj, array); + eldbus_message_iter_container_close(iter, subj); + eldbus_message_iter_basic_append(iter, 's', "/org/enlightenment/polkit/Agent"); + eldbus_proxy_send(pk_proxy, msg, NULL, NULL, -1); + } + + session_shutdown(); + + if (agent_iface) eldbus_service_object_unregister(agent_iface); + agent_iface = NULL; + if (owner_gain_timer) ecore_timer_del(owner_gain_timer); + owner_gain_timer = NULL; + + if (pk_proxy) eldbus_proxy_unref(pk_proxy); + pk_proxy = NULL; + if (pk_obj) eldbus_object_unref(pk_obj); + pk_obj = NULL; + + if (pk_proxy) eldbus_proxy_unref(pk_proxy); + pk_proxy = NULL; + if (pk_obj) eldbus_object_unref(pk_obj); + pk_obj = NULL; + if (ses_proxy2) eldbus_proxy_unref(ses_proxy2); + ses_proxy2 = NULL; + if (ses_proxy) eldbus_proxy_unref(ses_proxy); + ses_proxy = NULL; + if (ses_obj) eldbus_object_unref(ses_obj); + ses_obj = NULL; + if (ses_obj2) eldbus_object_unref(ses_obj2); + ses_obj2 = NULL; + + eldbus_connection_unref(pk_conn); + pk_conn = NULL; + + agent_request = EINA_FALSE; + agent_ok = EINA_FALSE; + eina_stringshare_replace(&session_path, NULL); + eina_stringshare_replace(&session_id, NULL); + eina_stringshare_replace(&session_user, NULL); + session_uid = 0; +}