[134] | 1 | # |
---|
| 2 | # Description: Add a new D-Bus operation StartGuestSession(). |
---|
| 3 | # If setup/teardown scripts are available in |
---|
| 4 | # /usr/share/gdm/guest-session/ (shipped by separate gdm-guest-user |
---|
| 5 | # package), run a guest session without requiring a password. |
---|
| 6 | # Guest sessions call /usr/share/gdm/guest-session/Xsession instead of |
---|
| 7 | # /etc/gdm/Xsession, so that we can wrap AppArmor (or other MAC |
---|
| 8 | # system) rules around it. |
---|
| 9 | # Ubuntu: https://wiki.ubuntu.com/DesktopTeam/Specs/Intrepid/GuestAccount |
---|
| 10 | # |
---|
| 11 | diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/daemon/gdm-local-display-factory.c gdm-2.28.0.new/daemon/gdm-local-display-factory.c |
---|
| 12 | --- gdm-2.28.0/daemon/gdm-local-display-factory.c 2009-09-22 06:05:27.000000000 +1000 |
---|
| 13 | +++ gdm-2.28.0.new/daemon/gdm-local-display-factory.c 2009-10-14 14:39:13.000000000 +1100 |
---|
| 14 | @@ -22,6 +22,8 @@ |
---|
| 15 | |
---|
| 16 | #include <stdlib.h> |
---|
| 17 | #include <stdio.h> |
---|
| 18 | +#include <errno.h> |
---|
| 19 | +#include <pwd.h> |
---|
| 20 | |
---|
| 21 | #include <glib.h> |
---|
| 22 | #include <glib/gi18n.h> |
---|
| 23 | @@ -51,6 +53,8 @@ |
---|
| 24 | #define HAL_DBUS_DEVICE_INTERFACE "org.freedesktop.Hal.Device" |
---|
| 25 | #define SEAT_PCI_DEVICE_CLASS 3 |
---|
| 26 | |
---|
| 27 | +#define GUEST_USERNAME "guest" |
---|
| 28 | + |
---|
| 29 | #define MAX_DISPLAY_FAILURES 5 |
---|
| 30 | |
---|
| 31 | struct GdmLocalDisplayFactoryPrivate |
---|
| 32 | @@ -234,6 +238,269 @@ |
---|
| 33 | return ret; |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | +/* GdmGuestDisplay */ |
---|
| 37 | + |
---|
| 38 | +typedef struct |
---|
| 39 | +{ |
---|
| 40 | + GdmTransientDisplayClass parent_class; |
---|
| 41 | +} GdmGuestDisplayClass; |
---|
| 42 | + |
---|
| 43 | +typedef struct |
---|
| 44 | +{ |
---|
| 45 | + GdmTransientDisplay parent; |
---|
| 46 | + GdmTransientDisplayPrivate *priv; |
---|
| 47 | +} GdmGuestDisplay; |
---|
| 48 | + |
---|
| 49 | +#define GDM_TYPE_GUEST_DISPLAY (gdm_guest_display_get_type ()) |
---|
| 50 | +#define GDM_GUEST_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GUEST_DISPLAY, GdmGuestDisplayClass)) |
---|
| 51 | +GType gdm_guest_display_get_type (void); |
---|
| 52 | +static void gdm_guest_display_class_init (GdmGuestDisplayClass *klass); |
---|
| 53 | +static void gdm_guest_display_init (GdmGuestDisplay *display) {} |
---|
| 54 | +GdmDisplay * gdm_guest_display_new (int display_number); |
---|
| 55 | +static gboolean gdm_guest_display_finish (GdmDisplay *display); |
---|
| 56 | + |
---|
| 57 | +G_DEFINE_TYPE (GdmGuestDisplay, gdm_guest_display, GDM_TYPE_TRANSIENT_DISPLAY); |
---|
| 58 | + |
---|
| 59 | +/* override timed_login_details for guest session */ |
---|
| 60 | +static void |
---|
| 61 | +gdm_guest_display_get_timed_login_details (GdmDisplay *display, |
---|
| 62 | + gboolean *enabledp, |
---|
| 63 | + char **usernamep, |
---|
| 64 | + int *delayp) |
---|
| 65 | +{ |
---|
| 66 | + g_debug ("GdmLocalDisplayFactory: Getting guest timed login details"); |
---|
| 67 | + *enabledp = TRUE; |
---|
| 68 | + *usernamep = g_strdup(GUEST_USERNAME); |
---|
| 69 | + *delayp = 0; |
---|
| 70 | +} |
---|
| 71 | + |
---|
| 72 | +static void |
---|
| 73 | +gdm_guest_display_class_init (GdmGuestDisplayClass *klass) |
---|
| 74 | +{ |
---|
| 75 | + GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass); |
---|
| 76 | + |
---|
| 77 | + display_class->get_timed_login_details = gdm_guest_display_get_timed_login_details; |
---|
| 78 | + display_class->finish = gdm_guest_display_finish; |
---|
| 79 | +} |
---|
| 80 | + |
---|
| 81 | +GdmDisplay * |
---|
| 82 | +gdm_guest_display_new (int display_number) |
---|
| 83 | +{ |
---|
| 84 | + GObject *object; |
---|
| 85 | + char *x11_display; |
---|
| 86 | + |
---|
| 87 | + x11_display = g_strdup_printf (":%d", display_number); |
---|
| 88 | + object = g_object_new (GDM_TYPE_GUEST_DISPLAY, |
---|
| 89 | + "x11-display-number", display_number, |
---|
| 90 | + "x11-display-name", x11_display, |
---|
| 91 | + NULL); |
---|
| 92 | + g_free (x11_display); |
---|
| 93 | + |
---|
| 94 | + return GDM_DISPLAY (object); |
---|
| 95 | +} |
---|
| 96 | + |
---|
| 97 | +static |
---|
| 98 | +gboolean |
---|
| 99 | +gdm_guest_display_finish (GdmDisplay *display) |
---|
| 100 | +{ |
---|
| 101 | + GError *err = NULL; |
---|
| 102 | + gboolean result; |
---|
| 103 | + gint status; |
---|
| 104 | + struct sigaction dfl, old_act; |
---|
| 105 | + const char* argv[] = { |
---|
| 106 | + "/usr/share/gdm/guest-session/guest-session-cleanup.sh", |
---|
| 107 | + GUEST_USERNAME, NULL}; |
---|
| 108 | + |
---|
| 109 | + /* temporarily reset SIGCHLD, we need it for g_spawn_sync */ |
---|
| 110 | + dfl.sa_handler = SIG_DFL; |
---|
| 111 | + dfl.sa_flags = SA_RESTART|SA_NOCLDSTOP; |
---|
| 112 | + sigemptyset (&dfl.sa_mask); |
---|
| 113 | + g_assert (sigaction (SIGCHLD, &dfl, &old_act) == 0); |
---|
| 114 | + |
---|
| 115 | + /* destroy guest user again */ |
---|
| 116 | + result = g_spawn_sync ("/", (gchar**) argv, NULL, 0, NULL, NULL, NULL, |
---|
| 117 | + NULL, &status, &err); |
---|
| 118 | + |
---|
| 119 | + g_assert (sigaction (SIGCHLD, &old_act, NULL) == 0); |
---|
| 120 | + |
---|
| 121 | + if (!result) { |
---|
| 122 | + g_warning ("gdm_guest_display_finish: Calling '%s %s' failed: %s", argv[0], |
---|
| 123 | + argv[1], err->message); |
---|
| 124 | + g_error_free (err); |
---|
| 125 | + } |
---|
| 126 | + |
---|
| 127 | + return GDM_DISPLAY_CLASS (gdm_guest_display_parent_class)->finish (display); |
---|
| 128 | +} |
---|
| 129 | + |
---|
| 130 | +/* End GdmGuestDisplay */ |
---|
| 131 | + |
---|
| 132 | +static gboolean |
---|
| 133 | +gdm_local_display_factory_setup_guest_account () |
---|
| 134 | +{ |
---|
| 135 | + GError *err = NULL; |
---|
| 136 | + gboolean result; |
---|
| 137 | + gchar *sout, *serr; |
---|
| 138 | + char *username; |
---|
| 139 | + gint status; |
---|
| 140 | + int len; |
---|
| 141 | + struct sigaction dfl, old_act; |
---|
| 142 | + const char* argv[] = { |
---|
| 143 | + "/usr/share/gdm/guest-session/guest-session-setup.sh", |
---|
| 144 | + NULL, NULL}; /* leave enough room for one argument */ |
---|
| 145 | + |
---|
| 146 | + g_debug ("gdm_local_display_factory_setup_guest_account: Calling guest-session-setup.sh"); |
---|
| 147 | + |
---|
| 148 | + /* temporarily reset SIGCHLD, we need it for g_spawn_sync */ |
---|
| 149 | + dfl.sa_handler = SIG_DFL; |
---|
| 150 | + dfl.sa_flags = SA_RESTART|SA_NOCLDSTOP; |
---|
| 151 | + sigemptyset (&dfl.sa_mask); |
---|
| 152 | + if (sigaction (SIGCHLD, &dfl, &old_act) < 0) { |
---|
| 153 | + g_warning("gdm_local_display_factory_setup_guest_account: failure to temporarily restore SIGCHLD: %s", |
---|
| 154 | + strerror(errno)); |
---|
| 155 | + return FALSE; |
---|
| 156 | + } |
---|
| 157 | + |
---|
| 158 | + /* call guest setup script */ |
---|
| 159 | + result = g_spawn_sync ("/", (gchar**) argv, NULL, 0, NULL, NULL, &sout, |
---|
| 160 | + &serr, &status, &err); |
---|
| 161 | + g_assert (sigaction (SIGCHLD, &old_act, NULL) == 0); |
---|
| 162 | + if (!result) { |
---|
| 163 | + g_warning ("gdm_local_display_factory_setup_guest_account: Calling %s failed: %s", argv[0], |
---|
| 164 | + err->message); |
---|
| 165 | + g_error_free (err); |
---|
| 166 | + return FALSE; |
---|
| 167 | + } |
---|
| 168 | + if (status != 0) { |
---|
| 169 | + g_warning ("gdm_local_display_factory_setup_guest_account: %s failed with status %i:\n%s\n%s", |
---|
| 170 | + argv[0], status, sout, serr); |
---|
| 171 | + g_free(sout); |
---|
| 172 | + g_free(serr); |
---|
| 173 | + return FALSE; |
---|
| 174 | + } |
---|
| 175 | + g_free (serr); |
---|
| 176 | + |
---|
| 177 | + /* extract user name from stdout */ |
---|
| 178 | + len = strlen (sout); |
---|
| 179 | + if (sout[len-1] == '\n') |
---|
| 180 | + sout[len-1] = 0; |
---|
| 181 | + username = strrchr (sout, '\n'); |
---|
| 182 | + if (!username || strcmp (username + 1, GUEST_USERNAME)) { |
---|
| 183 | + g_warning ("gdm_local_display_factory_setup_guest_account: no output, last line of stdout must have username; or username is not 'guest'"); |
---|
| 184 | + g_free (sout); |
---|
| 185 | + return FALSE; |
---|
| 186 | + } |
---|
| 187 | + g_debug ("gdm_local_display_factory_setup_guest_account: %s succeeded, username: '%s'", argv[0], username+1); |
---|
| 188 | + /* if we ever need to pass it to outside: */ |
---|
| 189 | + /* username = g_strdup (username + 1); */ |
---|
| 190 | + g_free (sout); |
---|
| 191 | + |
---|
| 192 | + return TRUE; |
---|
| 193 | +} |
---|
| 194 | + |
---|
| 195 | +static gboolean |
---|
| 196 | +switch_to_guest_display (GdmLocalDisplayFactory *factory) |
---|
| 197 | +{ |
---|
| 198 | + struct passwd *password; |
---|
| 199 | + DBusGProxy *proxy; |
---|
| 200 | + GPtrArray *sessions = NULL; |
---|
| 201 | + GError *error = NULL; |
---|
| 202 | + gboolean result = FALSE; |
---|
| 203 | + |
---|
| 204 | + password = getpwnam (GUEST_USERNAME); |
---|
| 205 | + if (!password) { |
---|
| 206 | + return FALSE; |
---|
| 207 | + } |
---|
| 208 | + |
---|
| 209 | + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, |
---|
| 210 | + "org.freedesktop.ConsoleKit", |
---|
| 211 | + "/org/freedesktop/ConsoleKit/Manager", |
---|
| 212 | + "org.freedesktop.ConsoleKit.Manager"); |
---|
| 213 | + |
---|
| 214 | + dbus_g_proxy_call (proxy, "GetSessionsForUnixUser", &error, |
---|
| 215 | + G_TYPE_UINT, password->pw_uid, G_TYPE_INVALID, |
---|
| 216 | + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, G_TYPE_INVALID); |
---|
| 217 | + g_object_unref(proxy); |
---|
| 218 | + if (error != NULL) { |
---|
| 219 | + g_warning ("Error getting guest sessions: %s", error->message); |
---|
| 220 | + g_error_free (error); |
---|
| 221 | + } |
---|
| 222 | + |
---|
| 223 | + if (sessions && sessions->len > 0) { |
---|
| 224 | + gchar *session_id = sessions->pdata[0]; |
---|
| 225 | + |
---|
| 226 | + g_debug ("GdmLocalDisplayFactory: Switching to guest session %s", session_id); |
---|
| 227 | + |
---|
| 228 | + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, |
---|
| 229 | + "org.freedesktop.ConsoleKit", |
---|
| 230 | + session_id, |
---|
| 231 | + "org.freedesktop.ConsoleKit.Session"); |
---|
| 232 | + result = dbus_g_proxy_call (proxy, "Activate", &error, G_TYPE_INVALID, G_TYPE_INVALID); |
---|
| 233 | + g_object_unref (proxy); |
---|
| 234 | + if (error != NULL) |
---|
| 235 | + { |
---|
| 236 | + g_warning ("Error activating guest session: %s", error->message); |
---|
| 237 | + g_error_free (error); |
---|
| 238 | + } |
---|
| 239 | + } |
---|
| 240 | + |
---|
| 241 | + if (sessions != NULL) { |
---|
| 242 | + gint i; |
---|
| 243 | + for (i = 0; i < sessions->len; i++) { |
---|
| 244 | + g_free (sessions->pdata[i]); |
---|
| 245 | + } |
---|
| 246 | + g_ptr_array_free (sessions, TRUE); |
---|
| 247 | + } |
---|
| 248 | + |
---|
| 249 | + return result; |
---|
| 250 | +} |
---|
| 251 | + |
---|
| 252 | +gboolean |
---|
| 253 | +gdm_local_display_factory_start_guest_session (GdmLocalDisplayFactory *factory, |
---|
| 254 | + char **id, |
---|
| 255 | + GError **error) |
---|
| 256 | +{ |
---|
| 257 | + GdmDisplay *display = NULL; |
---|
| 258 | + guint32 num; |
---|
| 259 | + |
---|
| 260 | + g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE); |
---|
| 261 | + |
---|
| 262 | + /* Switch to existing guest display */ |
---|
| 263 | + if (switch_to_guest_display (factory)) { |
---|
| 264 | + /* FIXME: How to return the ID of the guest display? It should |
---|
| 265 | + * be easy but I can't find how to get it */ |
---|
| 266 | + /*if (id != NULL) { |
---|
| 267 | + *id = g_strdup ("FIXME"); |
---|
| 268 | + }*/ |
---|
| 269 | + |
---|
| 270 | + /* FIXME: We should return TRUE here but this causes GDM to go |
---|
| 271 | + * crazy. Luckily we can return FALSE as we don't need |
---|
| 272 | + * any values returned from this call */ |
---|
| 273 | + return FALSE; |
---|
| 274 | + } |
---|
| 275 | + |
---|
| 276 | + if (!gdm_local_display_factory_setup_guest_account()) { |
---|
| 277 | + return FALSE; |
---|
| 278 | + } |
---|
| 279 | + |
---|
| 280 | + num = take_next_display_number (factory); |
---|
| 281 | + |
---|
| 282 | + g_debug ("GdmLocalDisplayFactory: Starting Guest Session %d", num); |
---|
| 283 | + |
---|
| 284 | + display = gdm_guest_display_new (num); |
---|
| 285 | + |
---|
| 286 | + /* FIXME: don't hardcode seat1? */ |
---|
| 287 | + g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL); |
---|
| 288 | + |
---|
| 289 | + store_display (factory, num, display); |
---|
| 290 | + |
---|
| 291 | + if (! gdm_display_manage (display) || ! gdm_display_get_id (display, id, NULL)) { |
---|
| 292 | + return FALSE; |
---|
| 293 | + } else { |
---|
| 294 | + g_object_unref (display); |
---|
| 295 | + return TRUE; |
---|
| 296 | + } |
---|
| 297 | +} |
---|
| 298 | + |
---|
| 299 | gboolean |
---|
| 300 | gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factory, |
---|
| 301 | const char *parent_display_id, |
---|
| 302 | diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/daemon/gdm-local-display-factory.h gdm-2.28.0.new/daemon/gdm-local-display-factory.h |
---|
| 303 | --- gdm-2.28.0/daemon/gdm-local-display-factory.h 2009-09-22 06:05:27.000000000 +1000 |
---|
| 304 | +++ gdm-2.28.0.new/daemon/gdm-local-display-factory.h 2009-10-14 14:34:31.000000000 +1100 |
---|
| 305 | @@ -65,6 +65,10 @@ |
---|
| 306 | char **id, |
---|
| 307 | GError **error); |
---|
| 308 | |
---|
| 309 | +gboolean gdm_local_display_factory_start_guest_session (GdmLocalDisplayFactory *factory, |
---|
| 310 | + char **id, |
---|
| 311 | + GError **error); |
---|
| 312 | + |
---|
| 313 | gboolean gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factory, |
---|
| 314 | const char *parent_display_id, |
---|
| 315 | const char *relay_address, |
---|
| 316 | diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/daemon/gdm-local-display-factory.xml gdm-2.28.0.new/daemon/gdm-local-display-factory.xml |
---|
| 317 | --- gdm-2.28.0/daemon/gdm-local-display-factory.xml 2009-09-22 06:05:27.000000000 +1000 |
---|
| 318 | +++ gdm-2.28.0.new/daemon/gdm-local-display-factory.xml 2009-10-14 14:34:31.000000000 +1100 |
---|
| 319 | @@ -9,5 +9,8 @@ |
---|
| 320 | <method name="CreateTransientDisplay"> |
---|
| 321 | <arg name="id" direction="out" type="o"/> |
---|
| 322 | </method> |
---|
| 323 | + <method name="StartGuestSession"> |
---|
| 324 | + <arg name="id" direction="out" type="o"/> |
---|
| 325 | + </method> |
---|
| 326 | </interface> |
---|
| 327 | </node> |
---|
| 328 | diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/data/gdm.conf.in gdm-2.28.0.new/data/gdm.conf.in |
---|
| 329 | --- gdm-2.28.0/data/gdm.conf.in 2009-10-14 14:34:30.000000000 +1100 |
---|
| 330 | +++ gdm-2.28.0.new/data/gdm.conf.in 2009-10-14 14:34:31.000000000 +1100 |
---|
| 331 | @@ -68,6 +68,9 @@ |
---|
| 332 | <allow send_destination="org.gnome.DisplayManager" |
---|
| 333 | send_interface="org.gnome.DisplayManager.LocalDisplayFactory" |
---|
| 334 | send_member="CreateTransientDisplay"/> |
---|
| 335 | + <allow send_destination="org.gnome.DisplayManager" |
---|
| 336 | + send_interface="org.gnome.DisplayManager.LocalDisplayFactory" |
---|
| 337 | + send_member="StartGuestSession"/> |
---|
| 338 | |
---|
| 339 | <allow send_destination="org.gnome.DisplayManager" |
---|
| 340 | send_interface="org.gnome.DisplayManager.Manager" |
---|