1 /*
2    Copyright (C) 2014 Red Hat Inc
3 
4    The Gnome Keyring Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8 
9    The Gnome Keyring Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with the Gnome Library; see the file COPYING.LIB.  If not,
16    <http://www.gnu.org/licenses/>.
17 
18    Author: Stef Walter <stefw@gnome.org>
19 */
20 
21 #include "config.h"
22 
23 #include "gkd-test.h"
24 
25 #include "daemon/control/gkd-control.h"
26 
27 #include "egg/egg-testing.h"
28 
29 #include <glib.h>
30 #include <glib/gstdio.h>
31 #include <gio/gio.h>
32 
33 #include <sys/wait.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 
37 typedef struct {
38 	GTestDBus *dbus;
39 	gchar *directory;
40 	GPid pid;
41 } Test;
42 
43 static void
setup(Test * test,gconstpointer unused)44 setup (Test *test,
45        gconstpointer unused)
46 {
47 	test->dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
48 	g_test_dbus_up (test->dbus);
49 
50 	test->directory = egg_tests_create_scratch_directory (
51 		SRCDIR "/daemon/dbus/fixtures/test.keyring",
52 		NULL);
53 }
54 
55 static void
teardown(Test * test,gconstpointer unused)56 teardown (Test *test,
57           gconstpointer unused)
58 {
59 	if (test->pid) {
60 		if (waitpid (test->pid, NULL, WNOHANG) != test->pid) {
61 			kill (test->pid, SIGTERM);
62 			g_assert_cmpint (waitpid (test->pid, NULL, 0), ==, test->pid);
63 		}
64 		g_spawn_close_pid (test->pid);
65 	}
66 
67 	egg_tests_remove_scratch_directory (test->directory);
68 	g_free (test->directory);
69 
70 	g_test_dbus_down (test->dbus);
71 	g_object_unref (test->dbus);
72 }
73 
74 static void
test_control_valid(Test * test,gconstpointer unused)75 test_control_valid (Test *test,
76                      gconstpointer unused)
77 {
78 	gchar *fixed = g_strdup_printf ("%s/xxxx", test->directory);
79 
80 	const gchar *argv[] = {
81 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
82 		"--control-directory", fixed,
83 		"--components=", NULL
84 	};
85 
86 	gchar **output;
87 	gint status;
88 	GPid pid;
89 
90 	output = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
91 
92 	g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), ==, fixed);
93 	g_strfreev (output);
94 
95 	g_assert (gkd_control_quit (fixed, 0));
96 	g_assert_cmpint (waitpid (pid, &status, 0), ==, pid);
97 	g_assert_cmpint (status, ==, 0);
98 
99 	g_free (fixed);
100 }
101 
102 static void
test_control_creates(Test * test,gconstpointer unused)103 test_control_creates (Test *test,
104                       gconstpointer unused)
105 {
106 	gchar *directory = g_build_filename (test->directory, "under", NULL);
107 
108 	const gchar *argv[] = {
109 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
110 		"--control-directory", directory,
111 		"--components=", NULL
112 	};
113 
114 	gchar **output;
115 
116 	output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
117 	g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), ==, directory);
118 	g_strfreev (output);
119 
120 	g_assert (g_file_test (directory, G_FILE_TEST_IS_DIR));
121 	g_free (directory);
122 }
123 
124 static void
test_control_noaccess(Test * test,gconstpointer unused)125 test_control_noaccess (Test *test,
126                       gconstpointer unused)
127 {
128 	gchar *noaccess = g_build_filename (test->directory, "under", NULL);
129 	gchar *directory = g_build_filename (test->directory, "under", "subdir", NULL);
130 
131 	const gchar *argv[] = {
132 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
133 		"--control-directory", directory,
134 		"--components=", NULL
135 	};
136 
137 	gchar **output;
138 
139 	if (g_mkdir_with_parents (noaccess, 0000) < 0)
140 		g_assert_not_reached ();
141 
142 	/* Should choose a different directory */
143 	output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
144 	g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), !=, directory);
145 	g_strfreev (output);
146 
147 	g_assert (!g_file_test (directory, G_FILE_TEST_IS_DIR));
148 	g_free (directory);
149 
150 	if (chmod (noaccess, 0700) < 0)
151 		g_assert_not_reached ();
152 	g_free (noaccess);
153 }
154 
155 static void
test_control_badperm(Test * test,gconstpointer unused)156 test_control_badperm (Test *test,
157                       gconstpointer unused)
158 {
159 	gchar *directory = g_build_filename (test->directory, "under", NULL);
160 
161 	const gchar *argv[] = {
162 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
163 		"--control-directory", directory,
164 		"--components=", NULL
165 	};
166 
167 	gchar **output;
168 
169 	if (g_mkdir_with_parents (directory, 0777) < 0)
170 		g_assert_not_reached ();
171 
172 	/* Should choose a different directory */
173 	output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
174 	g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), !=, directory);
175 	g_strfreev (output);
176 
177 	g_free (directory);
178 }
179 
180 static void
test_control_xdghome(Test * test,gconstpointer unused)181 test_control_xdghome (Test *test,
182                      gconstpointer unused)
183 {
184 	const gchar *argv[] = {
185 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
186 		"--components=", NULL
187 	};
188 
189 	gchar *directory;
190 	gchar *expected;
191 	GPid pid;
192 	gchar **output;
193 	gint status;
194 
195 	/* Control directory not printed when default */
196 	directory = g_build_filename (test->directory, "different", NULL);
197 	output = gkd_test_launch_daemon (test->directory, argv, &pid,
198 	                                 "XDG_RUNTIME_DIR", directory,
199 	                                 NULL);
200 
201 	expected = g_build_filename (directory, "/keyring", NULL);
202 	g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), ==, NULL);
203 	g_strfreev (output);
204 
205 	g_assert (gkd_control_quit (expected, 0));
206 	g_assert_cmpint (waitpid (pid, &status, 0), ==, pid);
207 	g_assert_cmpint (status, ==, 0);
208 
209 	g_free (directory);
210 	g_free (expected);
211 }
212 
213 static void
test_daemon_replace(Test * test,gconstpointer unused)214 test_daemon_replace (Test *test,
215                      gconstpointer unused)
216 {
217 	const gchar *argv[] = {
218 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
219 		"--components=", NULL
220 	};
221 
222 	const gchar *replace[] = {
223 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
224 		"--replace", "--components=", NULL
225 	};
226 
227 	gchar **output;
228 	gint status;
229 	GPid pid;
230 
231 	/* Start the first daemon */
232 	output = gkd_test_launch_daemon (test->directory, argv, &pid,
233 	                                 "XDG_RUNTIME_DIR", "/tmp/keyring-test-two",
234 	                                 NULL);
235 	g_strfreev (output);
236 
237 	/* Replace with the second daemon */
238 	output = gkd_test_launch_daemon (test->directory, replace, &test->pid,
239 	                                 "XDG_RUNTIME_DIR", "/tmp/keyring-test-two",
240 	                                 NULL);
241 	g_strfreev (output);
242 
243 	/* The first daemon should have exited cleanly here */
244 	g_assert_cmpint (waitpid (pid, &status, 0), ==, pid);
245 	g_assert_cmpint (status, ==, 0);
246 }
247 
248 #ifdef WITH_SSH
249 static void
test_ssh_agent(Test * test,gconstpointer unused)250 test_ssh_agent (Test *test,
251                         gconstpointer unused)
252 {
253 	gchar *auth_sock = g_build_filename (test->directory, "keyring", "ssh", NULL);
254 
255 	const gchar *argv[] = {
256 		BUILDDIR "/gnome-keyring-daemon", "--foreground",
257 		"--components=ssh-agent", NULL
258 	};
259 
260 	gchar **output;
261 
262 	output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
263 	g_assert_cmpstr (g_environ_getenv (output, "SSH_AUTH_SOCK"), ==, auth_sock);
264 	g_strfreev (output);
265 
266 	g_assert (g_file_test (auth_sock, G_FILE_TEST_EXISTS));
267 	g_free (auth_sock);
268 }
269 #endif
270 
271 int
main(int argc,char ** argv)272 main (int argc, char **argv)
273 {
274 	g_test_init (&argc, &argv, NULL);
275 
276 	g_test_add ("/daemon/startup/control/valid", Test, NULL,
277 	            setup, test_control_valid, teardown);
278 	g_test_add ("/daemon/startup/control/creates", Test, NULL,
279 	            setup, test_control_creates, teardown);
280 	g_test_add ("/daemon/startup/control/noaccess", Test, NULL,
281 	            setup, test_control_noaccess, teardown);
282 	g_test_add ("/daemon/startup/control/badperm", Test, NULL,
283 	            setup, test_control_badperm, teardown);
284 	g_test_add ("/daemon/startup/control/xdghome", Test, NULL,
285 	            setup, test_control_xdghome, teardown);
286 
287 	g_test_add ("/daemon/startup/replace", Test, NULL,
288 	            setup, test_daemon_replace, teardown);
289 #ifdef WITH_SSH
290 	g_test_add ("/daemon/startup/ssh-agent", Test, NULL,
291 	            setup, test_ssh_agent, teardown);
292 #endif
293 
294 	return g_test_run ();
295 }
296