Skip to content

Commit 921f753

Browse files
committed
WIP: qubes-gui-runner: get environment from systemd and pass it through to the session
1 parent b1c52ac commit 921f753

2 files changed

Lines changed: 145 additions & 3 deletions

File tree

gui-agent/Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
#
2121

2222
CC ?= gcc
23-
CFLAGS += -I../include/ `pkg-config --cflags vchan` -g -Wall -Wextra -Werror -fPIC \
23+
CFLAGS += -I../include/ `pkg-config --cflags vchan` \
24+
`pkg-config --cflags dbus-1` -g -Wall -Wextra -Werror -fPIC \
2425
-Wmissing-prototypes -Wstrict-prototypes -Wold-style-declaration \
2526
-Wold-style-definition
2627
OBJS = vmside.o txrx-vchan.o error.o list.o encoding.o
27-
LIBS = -lX11 -lXdamage -lXcomposite -lXfixes `pkg-config --libs vchan` -lqubesdb \
28-
-lunistring
28+
LIBS = -lX11 -lXdamage -lXcomposite -lXfixes `pkg-config --libs vchan` \
29+
`pkg-config --libs dbus-1` -lqubesdb -lunistring
2930

3031

3132
all: qubes-gui qubes-gui-runuser

gui-agent/qubes-gui-runuser.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,138 @@
3232
#include <pwd.h>
3333
#include <err.h>
3434
#include <qubesdb-client.h>
35+
#include <dbus/dbus-connection.h>
3536

3637
#ifdef HAVE_PAM
3738
#include <security/pam_appl.h>
3839
#endif
3940

4041
pid_t child_pid = 0;
4142

43+
static char **get_systemd_env_from_dbus(void)
44+
{
45+
DBusConnection *dbus_conn = NULL;
46+
DBusError error_data = { 0 };
47+
DBusMessage *env_request = NULL;
48+
const char *systemd_manager_str = "org.freedesktop.systemd1.Manager";
49+
const char *environment_str = "Environment";
50+
dbus_bool_t ret = FALSE;
51+
DBusMessage *env_reply = NULL;
52+
int reply_type = 0;
53+
DBusMessageIter reply_iter = { 0 };
54+
DBusMessageIter reply_inner_iter = { 0 };
55+
char *inner_iter_typesig = NULL;
56+
DBusMessageIter reply_arr_iter = { 0 };
57+
int arr_item_type = 0;
58+
const char *env_val = NULL;
59+
char **env_arr = NULL;
60+
size_t env_arr_len = 0;
61+
62+
dbus_error_init(&error_data);
63+
dbus_conn = dbus_bus_get(DBUS_BUS_SESSION, &error_data);
64+
if (dbus_conn == NULL) {
65+
warnx("Failed to initialize DBus, error name: '%s', error contents: '%s'\n",
66+
error_data.name,
67+
error_data.message);
68+
goto dbus_cleanup;
69+
}
70+
71+
/* dbus_bus_get sets up our process to be killed if the DBus connection
72+
* closes. We don't want that, turn that off.
73+
*/
74+
dbus_connection_set_on_disconnect(dbus_conn, FALSE);
75+
76+
env_request = dbus_message_new_method_call("org.freedesktop.systemd1",
77+
"/org/freedesktop/systemd1",
78+
"org.freedesktop.DBus.Properties",
79+
"Get");
80+
if (env_request == NULL) {
81+
warnx("Failed to create DBus method call!\n");
82+
goto dbus_cleanup;
83+
}
84+
85+
ret = dbus_message_append_args(env_request,
86+
DBUS_TYPE_STRING, &systemd_manager_str,
87+
DBUS_TYPE_STRING, &environment_str,
88+
DBUS_TYPE_INVALID);
89+
if (ret == FALSE) {
90+
warnx("Failed to append arguments to DBus method call!\n");
91+
goto dbus_cleanup;
92+
}
93+
94+
env_reply = dbus_connection_send_with_reply_and_block(dbus_conn,
95+
env_request,
96+
500,
97+
&error_data);
98+
if (env_reply == NULL) {
99+
warnx("Failed to request environment data from systemd, error name: '%s', error contents: '%s'\n",
100+
error_data.name,
101+
error_data.message);
102+
goto dbus_cleanup;
103+
}
104+
105+
reply_type = dbus_message_get_type(env_reply);
106+
if (reply_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
107+
warnx("Did not get expected method reply from systemd!\n");
108+
goto dbus_cleanup;
109+
}
110+
111+
ret = dbus_message_iter_init(env_reply, &reply_iter);
112+
if (ret == FALSE) {
113+
warnx("systemd returned no environment variables!\n");
114+
goto dbus_cleanup;
115+
}
116+
117+
if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT) {
118+
warnx("Did not get variant container from systemd!\n");
119+
goto dbus_cleanup;
120+
}
121+
dbus_message_iter_recurse(&reply_iter, &reply_inner_iter);
122+
123+
inner_iter_typesig = dbus_message_iter_get_signature(&reply_inner_iter);
124+
if (strcmp(inner_iter_typesig, "as") != 0) {
125+
warnx("Variant container from systemd does not contain a string array!\n");
126+
goto dbus_cleanup;
127+
}
128+
dbus_message_iter_recurse(&reply_inner_iter, &reply_arr_iter);
129+
130+
while ((current_type = dbus_message_iter_get_arg_type(&reply_arr_iter))
131+
!= DBUS_TYPE_INVALID) {
132+
if (current_type != DBUS_TYPE_STRING) {
133+
warnx("Non-string item found in string array!\n");
134+
goto dbus_cleanup;
135+
}
136+
dbus_message_iter_get_basic(&reply_arr_iter, &env_val);
137+
env_arr_len++;
138+
env_arr = reallocarray(env_arr, env_arr_len, sizeof(char *));
139+
if (env_arr == NULL)
140+
errx("Failed to allocate memory for environment array: %s\n",
141+
strerror(errno));
142+
env_arr[env_arr_len - 1] = strdup(env_val);
143+
if (env_arr[env_arr_len - 1] == NULL)
144+
errx("Failed to allocate memory for environment item: %s\n",
145+
strerror(errno));
146+
}
147+
148+
env_arr_len++;
149+
env_arr = reallocarray(env_arr, env_arr_len, sizeof(char *));
150+
if (env_arr == NULL)
151+
errx("Failed to allocate memory for environment array: %s\n",
152+
strerror(errno));
153+
env_arr[env_arr_len - 1] = NULL;
154+
155+
dbus_cleanup:
156+
if (dbus_conn != NULL)
157+
dbus_connection_unref(dbus_conn);
158+
if (env_request != NULL)
159+
dbus_message_unref(env_request);
160+
if (env_reply != NULL)
161+
dbus_message_unref(env_reply);
162+
if (inner_iter_typesig != NULL)
163+
dbus_free(inner_iter_typesig);
164+
return env_arr;
165+
}
166+
42167
#ifdef HAVE_PAM
43168
static int pam_conv_callback(int num_msg, const struct pam_message **msg,
44169
struct pam_response **resp, void *appdata_ptr __attribute__((__unused__)))
@@ -79,6 +204,8 @@ static pid_t do_execute(char *user, char *path, char **argv)
79204
int retval=0, status;
80205
char **env;
81206
char env_buf[256];
207+
char **systemd_env;
208+
char **systemd_env_iter;
82209
pam_handle_t *pamh=NULL;
83210
pid_t pid;
84211

@@ -111,6 +238,11 @@ static pid_t do_execute(char *user, char *path, char **argv)
111238
if (retval != PAM_SUCCESS)
112239
goto error;
113240

241+
/* TODO: This allocates a chunk of memory for strings, but we never free
242+
* it. Should we?
243+
*/
244+
systemd_env = get_systemd_env_from_dbus();
245+
114246
/* provide env variables to PAM and the X session */
115247
retval = snprintf(env_buf, sizeof(env_buf), "HOME=%s", pw->pw_dir);
116248
if ((unsigned int)retval >= sizeof(env_buf))
@@ -203,6 +335,15 @@ static pid_t do_execute(char *user, char *path, char **argv)
203335
}
204336
}
205337

338+
if (systemd_env != NULL) {
339+
for (systemd_env_iter = systemd_env; *systemd_env_iter != NULL;
340+
systemd_env_iter++) {
341+
retval = pam_putenv(pamh, *systemd_env_iter);
342+
if (retval != PAM_SUCCESS)
343+
goto error;
344+
}
345+
}
346+
206347
/* authenticate */
207348
retval = pam_authenticate(pamh, 0);
208349
if (retval != PAM_SUCCESS)

0 commit comments

Comments
 (0)