1 |
/* |
2 |
* Copyright Red Hat, Inc. 2007,2009. |
3 |
* All rights reserved. |
4 |
* |
5 |
* Redistribution and use in source and binary forms, with or without |
6 |
* modification, are permitted provided that the following conditions are met: |
7 |
* |
8 |
* * Redistributions of source code must retain the above copyright |
9 |
* notice, this list of conditions and the following disclaimer. |
10 |
* * Redistributions in binary form must reproduce the above copyright |
11 |
* notice, this list of conditions and the following disclaimer in |
12 |
* the documentation and/or other materials provided with the |
13 |
* distribution. |
14 |
* * Neither the name of Red Hat, Inc., nor the names of its |
15 |
* contributors may be used to endorse or promote products derived |
16 |
* from this software without specific prior written permission. |
17 |
* |
18 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
19 |
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
20 |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
21 |
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
22 |
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
23 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
24 |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
25 |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
26 |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
27 |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
28 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 |
* |
30 |
* Gate a process inside of a ConsoleKit session. |
31 |
* |
32 |
* We want to do this instead of doing it from inside of xinit because at the |
33 |
* point we're doing it, we've already added the user's UID to the list of |
34 |
* allowed clients for the X server, so the ConsoleKit daemon, which assumes |
35 |
* the user's UID, will be able to connect without needing to be able to read |
36 |
* the user's X cookies. |
37 |
*/ |
38 |
|
39 |
#include <sys/types.h> |
40 |
#include <sys/wait.h> |
41 |
#include <paths.h> |
42 |
#include <stdlib.h> |
43 |
#include <string.h> |
44 |
#include <syslog.h> |
45 |
#include <unistd.h> |
46 |
#include <ck-connector.h> |
47 |
#include <dbus/dbus.h> |
48 |
|
49 |
static void |
50 |
setbusenv(const char *var, const char *val) |
51 |
{ |
52 |
DBusConnection *conn; |
53 |
DBusMessage *req, *rep; |
54 |
DBusMessageIter iter, sub, subsub; |
55 |
DBusError error; |
56 |
|
57 |
dbus_error_init (&error); |
58 |
|
59 |
conn = dbus_bus_get(DBUS_BUS_SESSION, &error); |
60 |
if (conn == NULL) { |
61 |
return; |
62 |
} |
63 |
|
64 |
req = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); |
65 |
if (req == NULL) { |
66 |
return; |
67 |
} |
68 |
|
69 |
memset(&iter, 0, sizeof(iter)); |
70 |
memset(&sub, 0, sizeof(sub)); |
71 |
memset(&subsub, 0, sizeof(subsub)); |
72 |
dbus_message_iter_init_append(req, &iter); |
73 |
if (!dbus_message_set_destination(req, DBUS_SERVICE_DBUS) || |
74 |
!dbus_message_set_path(req, DBUS_PATH_DBUS) || |
75 |
!dbus_message_set_interface(req, DBUS_INTERFACE_DBUS) || |
76 |
!dbus_message_set_member(req, "UpdateActivationEnvironment") || |
77 |
!dbus_message_iter_open_container(&iter, |
78 |
DBUS_TYPE_ARRAY, |
79 |
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING |
80 |
DBUS_TYPE_STRING_AS_STRING |
81 |
DBUS_TYPE_STRING_AS_STRING |
82 |
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, |
83 |
&sub) || |
84 |
!dbus_message_iter_open_container(&sub, |
85 |
DBUS_TYPE_DICT_ENTRY, |
86 |
NULL, |
87 |
&subsub) || |
88 |
!dbus_message_iter_append_basic(&subsub, DBUS_TYPE_STRING, &var) || |
89 |
!dbus_message_iter_append_basic(&subsub, DBUS_TYPE_STRING, &val) || |
90 |
!dbus_message_iter_close_container(&sub, &subsub) || |
91 |
!dbus_message_iter_close_container(&iter, &sub)) { |
92 |
dbus_message_unref(req); |
93 |
return; |
94 |
} |
95 |
rep = dbus_connection_send_with_reply_and_block(conn, req, |
96 |
30000, &error); |
97 |
dbus_message_unref(req); |
98 |
if (rep) { |
99 |
dbus_message_unref(rep); |
100 |
} |
101 |
} |
102 |
|
103 |
int |
104 |
main(int argc, char **argv) |
105 |
{ |
106 |
CkConnector *ckc = NULL; |
107 |
DBusError error; |
108 |
const char *shell, *cookie; |
109 |
pid_t pid; |
110 |
int status; |
111 |
|
112 |
ckc = ck_connector_new(); |
113 |
if (ckc != NULL) { |
114 |
dbus_error_init (&error); |
115 |
if (ck_connector_open_session(ckc, &error)) { |
116 |
pid = fork(); |
117 |
switch (pid) { |
118 |
case -1: |
119 |
syslog(LOG_ERR, "error forking child"); |
120 |
break; |
121 |
case 0: |
122 |
cookie = ck_connector_get_cookie(ckc); |
123 |
setenv("XDG_SESSION_COOKIE", cookie, 1); |
124 |
setbusenv("XDG_SESSION_COOKIE", cookie); |
125 |
break; |
126 |
default: |
127 |
waitpid(pid, &status, 0); |
128 |
exit(status); |
129 |
break; |
130 |
} |
131 |
} else { |
132 |
syslog(LOG_ERR, "error connecting to console-kit"); |
133 |
} |
134 |
} else { |
135 |
syslog(LOG_ERR, "error setting up to connect to console-kit"); |
136 |
} |
137 |
if (argc > 1) { |
138 |
execvp(argv[1], argv + 1); |
139 |
} else { |
140 |
shell = getenv("SHELL"); |
141 |
if (shell == NULL) { |
142 |
shell = _PATH_BSHELL; |
143 |
} |
144 |
execlp(shell, shell, NULL); |
145 |
} |
146 |
_exit(1); |
147 |
} |