source: proiecte/PPPP/gdm/daemon/gdm-session-relay.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 41.9 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "config.h"
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <errno.h>
31#include <ctype.h>
32#include <pwd.h>
33#include <grp.h>
34
35#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
36#include <sched.h>
37#endif
38
39#include <glib.h>
40#include <glib/gi18n.h>
41#include <glib-object.h>
42#define DBUS_API_SUBJECT_TO_CHANGE
43#include <dbus/dbus-glib.h>
44#include <dbus/dbus-glib-lowlevel.h>
45
46#include "gdm-session-private.h"
47#include "gdm-session-relay.h"
48
49#define GDM_SESSION_RELAY_DBUS_PATH      "/org/gnome/DisplayManager/SessionRelay"
50#define GDM_SESSION_RELAY_DBUS_INTERFACE "org.gnome.DisplayManager.SessionRelay"
51
52#define GDM_SESSION_RELAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_RELAY, GdmSessionRelayPrivate))
53
54struct GdmSessionRelayPrivate
55{
56        DBusServer     *server;
57        char           *server_address;
58        DBusConnection *session_connection;
59};
60
61enum {
62        PROP_0,
63};
64
65enum {
66        CONNECTED,
67        DISCONNECTED,
68        LAST_SIGNAL
69};
70
71static guint signals [LAST_SIGNAL] = { 0, };
72
73static void     gdm_session_relay_class_init    (GdmSessionRelayClass *klass);
74static void     gdm_session_relay_init          (GdmSessionRelay      *session_relay);
75static void     gdm_session_relay_finalize      (GObject              *object);
76static void     gdm_session_iface_init          (GdmSessionIface      *iface);
77
78G_DEFINE_TYPE_WITH_CODE (GdmSessionRelay,
79                         gdm_session_relay,
80                         G_TYPE_OBJECT,
81                         G_IMPLEMENT_INTERFACE (GDM_TYPE_SESSION,
82                                                gdm_session_iface_init))
83
84static gboolean
85send_dbus_message (DBusConnection *connection,
86                   DBusMessage    *message)
87{
88        gboolean is_connected;
89        gboolean sent;
90
91        g_return_val_if_fail (message != NULL, FALSE);
92
93        if (connection == NULL) {
94                g_debug ("GdmSessionRelay: There is no valid connection");
95                return FALSE;
96        }
97
98        is_connected = dbus_connection_get_is_connected (connection);
99        if (! is_connected) {
100                g_warning ("Not connected!");
101                return FALSE;
102        }
103
104        sent = dbus_connection_send (connection, message, NULL);
105
106        return sent;
107}
108
109static void
110send_dbus_string_signal (GdmSessionRelay *session_relay,
111                         const char      *name,
112                         const char      *text)
113{
114        DBusMessage    *message;
115        DBusMessageIter iter;
116
117        g_return_if_fail (session_relay != NULL);
118
119        g_debug ("GdmSessionRelay: sending signal %s", name);
120        message = dbus_message_new_signal (GDM_SESSION_RELAY_DBUS_PATH,
121                                           GDM_SESSION_RELAY_DBUS_INTERFACE,
122                                           name);
123
124        dbus_message_iter_init_append (message, &iter);
125        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text);
126
127        if (! send_dbus_message (session_relay->priv->session_connection, message)) {
128                g_debug ("GdmSessionRelay: Could not send %s signal", name);
129        }
130
131        dbus_message_unref (message);
132}
133
134static void
135send_dbus_string_string_signal (GdmSessionRelay *session_relay,
136                                const char      *name,
137                                const char      *text1,
138                                const char      *text2)
139{
140        DBusMessage    *message;
141        DBusMessageIter iter;
142
143        g_return_if_fail (session_relay != NULL);
144
145        g_debug ("GdmSessionRelay: sending signal %s", name);
146        message = dbus_message_new_signal (GDM_SESSION_RELAY_DBUS_PATH,
147                                           GDM_SESSION_RELAY_DBUS_INTERFACE,
148                                           name);
149
150        dbus_message_iter_init_append (message, &iter);
151        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text1);
152        dbus_message_iter_init_append (message, &iter);
153        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text2);
154
155        if (! send_dbus_message (session_relay->priv->session_connection, message)) {
156                g_debug ("GdmSessionRelay: Could not send %s signal", name);
157        }
158
159        dbus_message_unref (message);
160}
161
162static void
163send_dbus_void_signal (GdmSessionRelay *session_relay,
164                       const char      *name)
165{
166        DBusMessage    *message;
167
168        g_return_if_fail (session_relay != NULL);
169
170        g_debug ("GdmSessionRelay: sending signal %s", name);
171        message = dbus_message_new_signal (GDM_SESSION_RELAY_DBUS_PATH,
172                                           GDM_SESSION_RELAY_DBUS_INTERFACE,
173                                           name);
174
175        if (! send_dbus_message (session_relay->priv->session_connection, message)) {
176                g_debug ("GdmSessionRelay: Could not send %s signal", name);
177        }
178
179        dbus_message_unref (message);
180}
181
182static void
183gdm_session_relay_open (GdmSession *session)
184{
185        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
186        send_dbus_void_signal (impl, "Open");
187}
188
189static void
190gdm_session_relay_close (GdmSession *session)
191{
192        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
193        send_dbus_void_signal (impl, "Close");
194}
195
196static void
197gdm_session_relay_setup (GdmSession *session,
198                         const char *service_name)
199{
200        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
201        send_dbus_string_signal (impl, "Setup", service_name);
202}
203
204static void
205gdm_session_relay_setup_for_user (GdmSession *session,
206                                  const char *service_name,
207                                  const char *username)
208{
209        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
210        send_dbus_string_string_signal (impl, "SetupForUser", service_name, username);
211}
212
213static void
214gdm_session_relay_authenticate (GdmSession *session)
215{
216        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
217        send_dbus_void_signal (impl, "Authenticate");
218}
219
220static void
221gdm_session_relay_authorize (GdmSession *session)
222{
223        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
224        send_dbus_void_signal (impl, "Authorize");
225}
226
227static void
228gdm_session_relay_accredit (GdmSession *session,
229                            int         cred_flag)
230{
231        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
232
233        switch (cred_flag) {
234        case GDM_SESSION_CRED_ESTABLISH:
235                send_dbus_void_signal (impl, "EstablishCredentials");
236                break;
237        case GDM_SESSION_CRED_REFRESH:
238                send_dbus_void_signal (impl, "RefreshCredentials");
239                break;
240        default:
241                g_assert_not_reached ();
242        }
243}
244
245static void
246gdm_session_relay_answer_query (GdmSession *session,
247                                const char *text)
248{
249        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
250        send_dbus_string_signal (impl, "AnswerQuery", text);
251}
252
253static void
254gdm_session_relay_select_session (GdmSession *session,
255                                  const char *text)
256{
257        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
258        send_dbus_string_signal (impl, "SessionSelected", text);
259}
260
261static void
262gdm_session_relay_select_language (GdmSession *session,
263                                   const char *text)
264{
265        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
266        send_dbus_string_signal (impl, "LanguageSelected", text);
267}
268
269static void
270gdm_session_relay_select_layout (GdmSession *session,
271                                 const char *text)
272{
273        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
274        send_dbus_string_signal (impl, "LayoutSelected", text);
275}
276
277static void
278gdm_session_relay_select_user (GdmSession *session,
279                               const char *text)
280{
281        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
282        send_dbus_string_signal (impl, "UserSelected", text);
283}
284
285static void
286gdm_session_relay_cancel (GdmSession *session)
287{
288        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
289
290        send_dbus_void_signal (impl, "Cancelled");
291}
292
293static void
294gdm_session_relay_start_session (GdmSession *session)
295{
296        GdmSessionRelay *impl = GDM_SESSION_RELAY (session);
297
298        send_dbus_void_signal (impl, "StartSession");
299}
300
301/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
302 * sockets are only available on Linux.
303 */
304static char *
305generate_address (void)
306{
307        char *path;
308#if defined (__linux__)
309        int   i;
310        char  tmp[9];
311
312        for (i = 0; i < 8; i++) {
313                if (g_random_int_range (0, 2) == 0) {
314                        tmp[i] = g_random_int_range ('a', 'z' + 1);
315                } else {
316                        tmp[i] = g_random_int_range ('A', 'Z' + 1);
317                }
318        }
319        tmp[8] = '\0';
320
321        path = g_strdup_printf ("unix:abstract=/tmp/gdm-session-%s", tmp);
322#else
323        path = g_strdup ("unix:tmpdir=/tmp");
324#endif
325
326        return path;
327}
328
329static DBusHandlerResult
330handle_info_query (GdmSessionRelay *session_relay,
331                   DBusConnection  *connection,
332                   DBusMessage     *message)
333{
334        DBusMessage *reply;
335        DBusError    error;
336        const char  *text;
337
338        dbus_error_init (&error);
339        if (! dbus_message_get_args (message, &error,
340                                     DBUS_TYPE_STRING, &text,
341                                     DBUS_TYPE_INVALID)) {
342                g_warning ("ERROR: %s", error.message);
343        }
344
345        g_debug ("GdmSessionRelay: InfoQuery: %s", text);
346
347        reply = dbus_message_new_method_return (message);
348        dbus_connection_send (connection, reply, NULL);
349        dbus_message_unref (reply);
350
351        _gdm_session_info_query (GDM_SESSION (session_relay), text);
352
353        return DBUS_HANDLER_RESULT_HANDLED;
354}
355
356static DBusHandlerResult
357handle_secret_info_query (GdmSessionRelay *session_relay,
358                          DBusConnection  *connection,
359                          DBusMessage     *message)
360{
361        DBusMessage *reply;
362        DBusError    error;
363        const char  *text;
364
365        text = NULL;
366
367        dbus_error_init (&error);
368        if (! dbus_message_get_args (message, &error,
369                                     DBUS_TYPE_STRING, &text,
370                                     DBUS_TYPE_INVALID)) {
371                g_warning ("ERROR: %s", error.message);
372        }
373
374        g_debug ("GdmSessionRelay: SecretInfoQuery: %s", text);
375
376        reply = dbus_message_new_method_return (message);
377        dbus_connection_send (connection, reply, NULL);
378        dbus_message_unref (reply);
379
380        _gdm_session_secret_info_query (GDM_SESSION (session_relay), text);
381
382        return DBUS_HANDLER_RESULT_HANDLED;
383}
384
385static DBusHandlerResult
386handle_info (GdmSessionRelay *session_relay,
387             DBusConnection  *connection,
388             DBusMessage     *message)
389{
390        DBusMessage *reply;
391        DBusError    error;
392        const char  *text;
393
394        text = NULL;
395
396        dbus_error_init (&error);
397        if (! dbus_message_get_args (message, &error,
398                                     DBUS_TYPE_STRING, &text,
399                                     DBUS_TYPE_INVALID)) {
400                g_warning ("ERROR: %s", error.message);
401        }
402
403        g_debug ("GdmSessionRelay: Info: %s", text);
404
405        reply = dbus_message_new_method_return (message);
406        dbus_connection_send (connection, reply, NULL);
407        dbus_message_unref (reply);
408
409        _gdm_session_info (GDM_SESSION (session_relay), text);
410
411        return DBUS_HANDLER_RESULT_HANDLED;
412}
413
414static DBusHandlerResult
415handle_problem (GdmSessionRelay *session_relay,
416             DBusConnection  *connection,
417             DBusMessage     *message)
418{
419        DBusMessage *reply;
420        DBusError    error;
421        const char  *text;
422
423        text = NULL;
424
425        dbus_error_init (&error);
426        if (! dbus_message_get_args (message, &error,
427                                     DBUS_TYPE_STRING, &text,
428                                     DBUS_TYPE_INVALID)) {
429                g_warning ("ERROR: %s", error.message);
430        }
431
432        g_debug ("GdmSessionRelay: Problem: %s", text);
433
434        reply = dbus_message_new_method_return (message);
435        dbus_connection_send (connection, reply, NULL);
436        dbus_message_unref (reply);
437
438        _gdm_session_problem (GDM_SESSION (session_relay), text);
439
440        return DBUS_HANDLER_RESULT_HANDLED;
441}
442
443static DBusHandlerResult
444handle_setup_complete (GdmSessionRelay *session_relay,
445                       DBusConnection  *connection,
446                       DBusMessage     *message)
447{
448        DBusMessage *reply;
449        DBusError    error;
450
451        dbus_error_init (&error);
452
453        g_debug ("GdmSessionRelay: SetupComplete");
454
455        reply = dbus_message_new_method_return (message);
456        dbus_connection_send (connection, reply, NULL);
457        dbus_message_unref (reply);
458
459        _gdm_session_setup_complete (GDM_SESSION (session_relay));
460
461        return DBUS_HANDLER_RESULT_HANDLED;
462}
463
464static DBusHandlerResult
465handle_setup_failed (GdmSessionRelay *session_relay,
466                     DBusConnection  *connection,
467                     DBusMessage     *message)
468{
469        DBusMessage *reply;
470        DBusError    error;
471
472        dbus_error_init (&error);
473
474        g_debug ("GdmSessionRelay: SetupFailed");
475
476        reply = dbus_message_new_method_return (message);
477        dbus_connection_send (connection, reply, NULL);
478        dbus_message_unref (reply);
479
480        _gdm_session_setup_failed (GDM_SESSION (session_relay), NULL);
481
482        return DBUS_HANDLER_RESULT_HANDLED;
483}
484
485
486static DBusHandlerResult
487handle_authenticated (GdmSessionRelay *session_relay,
488                      DBusConnection  *connection,
489                      DBusMessage     *message)
490{
491        DBusMessage *reply;
492        DBusError    error;
493
494        dbus_error_init (&error);
495
496        g_debug ("GdmSessionRelay: Authenticated");
497
498        reply = dbus_message_new_method_return (message);
499        dbus_connection_send (connection, reply, NULL);
500        dbus_message_unref (reply);
501
502        _gdm_session_authenticated (GDM_SESSION (session_relay));
503
504        return DBUS_HANDLER_RESULT_HANDLED;
505}
506
507static DBusHandlerResult
508handle_authentication_failed (GdmSessionRelay *session_relay,
509                              DBusConnection  *connection,
510                              DBusMessage     *message)
511{
512        DBusMessage *reply;
513        DBusError    error;
514
515        dbus_error_init (&error);
516
517        g_debug ("GdmSessionRelay: AuthenticationFailed");
518
519        reply = dbus_message_new_method_return (message);
520        dbus_connection_send (connection, reply, NULL);
521        dbus_message_unref (reply);
522
523        _gdm_session_authentication_failed (GDM_SESSION (session_relay), NULL);
524
525        return DBUS_HANDLER_RESULT_HANDLED;
526}
527
528static DBusHandlerResult
529handle_authorized (GdmSessionRelay *session_relay,
530                   DBusConnection  *connection,
531                   DBusMessage     *message)
532{
533        DBusMessage *reply;
534        DBusError    error;
535
536        dbus_error_init (&error);
537
538        g_debug ("GdmSessionRelay: Authorized");
539
540        reply = dbus_message_new_method_return (message);
541        dbus_connection_send (connection, reply, NULL);
542        dbus_message_unref (reply);
543
544        _gdm_session_authorized (GDM_SESSION (session_relay));
545
546        return DBUS_HANDLER_RESULT_HANDLED;
547}
548
549static DBusHandlerResult
550handle_authorization_failed (GdmSessionRelay *session_relay,
551                             DBusConnection  *connection,
552                             DBusMessage     *message)
553{
554        DBusMessage *reply;
555        DBusError    error;
556
557        dbus_error_init (&error);
558
559        g_debug ("GdmSessionRelay: AuthorizationFailed");
560
561        reply = dbus_message_new_method_return (message);
562        dbus_connection_send (connection, reply, NULL);
563        dbus_message_unref (reply);
564
565        _gdm_session_authorization_failed (GDM_SESSION (session_relay), NULL);
566
567        return DBUS_HANDLER_RESULT_HANDLED;
568}
569
570static DBusHandlerResult
571handle_accredited (GdmSessionRelay *session_relay,
572                   DBusConnection  *connection,
573                   DBusMessage     *message)
574{
575        DBusMessage *reply;
576        DBusError    error;
577
578        dbus_error_init (&error);
579
580        g_debug ("GdmSessionRelay: Accredited");
581
582        reply = dbus_message_new_method_return (message);
583        dbus_connection_send (connection, reply, NULL);
584        dbus_message_unref (reply);
585
586        _gdm_session_accredited (GDM_SESSION (session_relay));
587
588        return DBUS_HANDLER_RESULT_HANDLED;
589}
590
591static DBusHandlerResult
592handle_accreditation_failed (GdmSessionRelay *session_relay,
593                             DBusConnection  *connection,
594                             DBusMessage     *message)
595{
596        DBusMessage *reply;
597        DBusError    error;
598
599        dbus_error_init (&error);
600
601        g_debug ("GdmSessionRelay: AccreditationFailed");
602
603        reply = dbus_message_new_method_return (message);
604        dbus_connection_send (connection, reply, NULL);
605        dbus_message_unref (reply);
606
607        _gdm_session_accreditation_failed (GDM_SESSION (session_relay), NULL);
608
609        return DBUS_HANDLER_RESULT_HANDLED;
610}
611
612static DBusHandlerResult
613handle_session_started (GdmSessionRelay *session_relay,
614                        DBusConnection  *connection,
615                        DBusMessage     *message)
616{
617        DBusMessage *reply;
618        DBusError    error;
619        int          pid;
620
621        dbus_error_init (&error);
622
623        pid = 0;
624        if (! dbus_message_get_args (message,
625                                     &error,
626                                     DBUS_TYPE_INT32, &pid,
627                                     DBUS_TYPE_INVALID)) {
628                g_warning ("ERROR: %s", error.message);
629        }
630
631        g_debug ("GdmSessionRelay: SessionStarted");
632
633        reply = dbus_message_new_method_return (message);
634        dbus_connection_send (connection, reply, NULL);
635        dbus_message_unref (reply);
636
637        _gdm_session_session_started (GDM_SESSION (session_relay),
638                                      pid);
639
640        return DBUS_HANDLER_RESULT_HANDLED;
641}
642
643static DBusHandlerResult
644handle_session_stopped (GdmSessionRelay *session_relay,
645                        DBusConnection  *connection,
646                        DBusMessage     *message)
647{
648        DBusMessage *reply;
649        DBusError    error;
650
651        dbus_error_init (&error);
652
653        g_debug ("GdmSessionRelay: SessionStopped");
654
655        reply = dbus_message_new_method_return (message);
656        dbus_connection_send (connection, reply, NULL);
657        dbus_message_unref (reply);
658
659#if 0
660        _gdm_session_session_stopped (GDM_SESSION (session_relay));
661#endif
662
663        return DBUS_HANDLER_RESULT_HANDLED;
664}
665
666static DBusHandlerResult
667handle_opened (GdmSessionRelay *session_relay,
668               DBusConnection  *connection,
669               DBusMessage     *message)
670{
671        DBusMessage *reply;
672        DBusError    error;
673
674        dbus_error_init (&error);
675
676        g_debug ("GdmSessionRelay: Opened");
677
678        reply = dbus_message_new_method_return (message);
679        dbus_connection_send (connection, reply, NULL);
680        dbus_message_unref (reply);
681
682        _gdm_session_opened (GDM_SESSION (session_relay));
683
684        return DBUS_HANDLER_RESULT_HANDLED;
685}
686
687static DBusHandlerResult
688session_handle_child_message (DBusConnection *connection,
689                              DBusMessage    *message,
690                              void           *user_data)
691{
692        GdmSessionRelay *session_relay = GDM_SESSION_RELAY (user_data);
693
694        if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "InfoQuery")) {
695                return handle_info_query (session_relay, connection, message);
696        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SecretInfoQuery")) {
697                return handle_secret_info_query (session_relay, connection, message);
698        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Info")) {
699                return handle_info (session_relay, connection, message);
700        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Problem")) {
701                return handle_problem (session_relay, connection, message);
702        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupComplete")) {
703                return handle_setup_complete (session_relay, connection, message);
704        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SetupFailed")) {
705                return handle_setup_failed (session_relay, connection, message);
706        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Authenticated")) {
707                return handle_authenticated (session_relay, connection, message);
708        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AuthenticationFailed")) {
709                return handle_authentication_failed (session_relay, connection, message);
710        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Authorized")) {
711                return handle_authorized (session_relay, connection, message);
712        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AuthorizationFailed")) {
713                return handle_authorization_failed (session_relay, connection, message);
714        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Accredited")) {
715                return handle_accredited (session_relay, connection, message);
716        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "AccreditationFailed")) {
717                return handle_accreditation_failed (session_relay, connection, message);
718        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStarted")) {
719                return handle_session_started (session_relay, connection, message);
720        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "SessionStopped")) {
721                return handle_session_stopped (session_relay, connection, message);
722        } else if (dbus_message_is_method_call (message, GDM_SESSION_RELAY_DBUS_INTERFACE, "Opened")) {
723                return handle_opened (session_relay, connection, message);
724        }
725
726        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
727}
728
729static DBusHandlerResult
730do_introspect (DBusConnection *connection,
731               DBusMessage    *message)
732{
733        DBusMessage *reply;
734        GString     *xml;
735        char        *xml_string;
736
737        g_debug ("GdmSessionRelay: Do introspect");
738
739        /* standard header */
740        xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
741                            "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
742                            "<node>\n"
743                            "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
744                            "    <method name=\"Introspect\">\n"
745                            "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
746                            "    </method>\n"
747                            "  </interface>\n");
748
749        /* interface */
750        xml = g_string_append (xml,
751                               "  <interface name=\"org.gnome.DisplayManager.SessionRelay\">\n"
752                               "    <method name=\"Opened\">\n"
753                               "    </method>\n"
754                               "    <method name=\"SetupComplete\">\n"
755                               "    </method>\n"
756                               "    <method name=\"SetupFailed\">\n"
757                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
758                               "    </method>\n"
759                               "    <method name=\"ResetComplete\">\n"
760                               "    </method>\n"
761                               "    <method name=\"RestFailed\">\n"
762                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
763                               "    </method>\n"
764                               "    <method name=\"Authenticated\">\n"
765                               "    </method>\n"
766                               "    <method name=\"AuthenticationFailed\">\n"
767                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
768                               "    </method>\n"
769                               "    <method name=\"Authorized\">\n"
770                               "    </method>\n"
771                               "    <method name=\"AuthorizationFailed\">\n"
772                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
773                               "    </method>\n"
774                               "    <method name=\"Accredited\">\n"
775                               "    </method>\n"
776                               "    <method name=\"AccreditationFailed\">\n"
777                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
778                               "    </method>\n"
779                               "    <method name=\"InfoQuery\">\n"
780                               "      <arg name=\"text\" type=\"s\"/>\n"
781                               "    </method>\n"
782                               "    <method name=\"SecretInfoQuery\">\n"
783                               "      <arg name=\"text\" type=\"s\"/>\n"
784                               "    </method>\n"
785                               "    <method name=\"Info\">\n"
786                               "      <arg name=\"text\" type=\"s\"/>\n"
787                               "    </method>\n"
788                               "    <method name=\"Problem\">\n"
789                               "      <arg name=\"text\" type=\"s\"/>\n"
790                               "    </method>\n"
791                               "    <method name=\"SessionStarted\">\n"
792                               "    </method>\n"
793                               "    <method name=\"SessionStopped\">\n"
794                               "    </method>\n"
795                               "    <signal name=\"Reset\">\n"
796                               "    </signal>\n"
797                               "    <signal name=\"Setup\">\n"
798                               "      <arg name=\"service_name\" type=\"s\"/>\n"
799                               "    </signal>\n"
800                               "    <signal name=\"SetupForUser\">\n"
801                               "      <arg name=\"service_name\" type=\"s\"/>\n"
802                               "      <arg name=\"username\" type=\"s\"/>\n"
803                               "    </signal>\n"
804                               "    <signal name=\"Authenticate\">\n"
805                               "    </signal>\n"
806                               "    <signal name=\"Authorize\">\n"
807                               "    </signal>\n"
808                               "    <signal name=\"EstablishCredentials\">\n"
809                               "    </signal>\n"
810                               "    <signal name=\"RefreshCredentials\">\n"
811                               "    </signal>\n"
812
813                               "    <signal name=\"Open\">\n"
814                               "    </signal>\n"
815                               "    <signal name=\"Close\">\n"
816                               "    </signal>\n"
817                               "    <signal name=\"StartSession\">\n"
818                               "    </signal>\n"
819                               "    <signal name=\"AnswerQuery\">\n"
820                               "      <arg name=\"text\" type=\"s\"/>\n"
821                               "    </signal>\n"
822                               "    <signal name=\"LanguageSelected\">\n"
823                               "      <arg name=\"language\" type=\"s\"/>\n"
824                               "    </signal>\n"
825                               "    <signal name=\"LayoutSelected\">\n"
826                               "      <arg name=\"layout\" type=\"s\"/>\n"
827                               "    </signal>\n"
828                               "    <signal name=\"SessionSelected\">\n"
829                               "      <arg name=\"session\" type=\"s\"/>\n"
830                               "    </signal>\n"
831                               "    <signal name=\"UserSelected\">\n"
832                               "      <arg name=\"session\" type=\"s\"/>\n"
833                               "    </signal>\n"
834                               "    <signal name=\"Cancelled\">\n"
835                               "      <arg name=\"session\" type=\"s\"/>\n"
836                               "    </signal>\n"
837                               "  </interface>\n");
838
839        reply = dbus_message_new_method_return (message);
840
841        xml = g_string_append (xml, "</node>\n");
842        xml_string = g_string_free (xml, FALSE);
843
844        dbus_message_append_args (reply,
845                                  DBUS_TYPE_STRING, &xml_string,
846                                  DBUS_TYPE_INVALID);
847
848        g_free (xml_string);
849
850        if (reply == NULL) {
851                g_error ("No memory");
852        }
853
854        if (! dbus_connection_send (connection, reply, NULL)) {
855                g_error ("No memory");
856        }
857
858        dbus_message_unref (reply);
859
860        return DBUS_HANDLER_RESULT_HANDLED;
861}
862
863static DBusHandlerResult
864session_relay_message_handler (DBusConnection  *connection,
865                                DBusMessage     *message,
866                                void            *user_data)
867{
868        const char *dbus_destination = dbus_message_get_destination (message);
869        const char *dbus_path        = dbus_message_get_path (message);
870        const char *dbus_interface   = dbus_message_get_interface (message);
871        const char *dbus_member      = dbus_message_get_member (message);
872
873        g_debug ("GdmSessionRelay: session_relay_message_handler: destination=%s obj_path=%s interface=%s method=%s",
874                 dbus_destination ? dbus_destination : "(null)",
875                 dbus_path        ? dbus_path        : "(null)",
876                 dbus_interface   ? dbus_interface   : "(null)",
877                 dbus_member      ? dbus_member      : "(null)");
878
879        if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
880                DBusMessage *reply;
881
882                reply = dbus_message_new_method_return (message);
883
884                if (reply == NULL) {
885                        g_error ("No memory");
886                }
887
888                if (! dbus_connection_send (connection, reply, NULL)) {
889                        g_error ("No memory");
890                }
891
892                dbus_message_unref (reply);
893
894                return DBUS_HANDLER_RESULT_HANDLED;
895        } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
896                   strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
897
898                /*dbus_connection_unref (connection);*/
899
900                return DBUS_HANDLER_RESULT_HANDLED;
901        } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
902                return do_introspect (connection, message);
903        } else {
904                return session_handle_child_message (connection, message, user_data);
905        }
906
907        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
908}
909
910static void
911session_relay_unregister_handler (DBusConnection  *connection,
912                                   void            *user_data)
913{
914        g_debug ("session_relay_unregister_handler");
915}
916
917static DBusHandlerResult
918connection_filter_function (DBusConnection *connection,
919                            DBusMessage    *message,
920                            void           *user_data)
921{
922        GdmSessionRelay *session_relay  = GDM_SESSION_RELAY (user_data);
923        const char      *dbus_path      = dbus_message_get_path (message);
924        const char      *dbus_interface = dbus_message_get_interface (message);
925        const char      *dbus_message   = dbus_message_get_member (message);
926
927        g_debug ("GdmSessionRelay: obj_path=%s interface=%s method=%s",
928                 dbus_path      ? dbus_path      : "(null)",
929                 dbus_interface ? dbus_interface : "(null)",
930                 dbus_message   ? dbus_message   : "(null)");
931
932        if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
933            && strcmp (dbus_path, DBUS_PATH_LOCAL) == 0) {
934
935                g_debug ("GdmSessionRelay: Disconnected");
936
937                dbus_connection_unref (connection);
938                session_relay->priv->session_connection = NULL;
939
940                g_signal_emit (session_relay, signals[DISCONNECTED], 0);
941        } else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
942
943
944        } else {
945                return session_relay_message_handler (connection, message, user_data);
946        }
947
948        return DBUS_HANDLER_RESULT_HANDLED;
949}
950
951static dbus_bool_t
952allow_user_function (DBusConnection *connection,
953                     unsigned long   uid,
954                     void           *data)
955{
956        if (uid == 0) {
957                return TRUE;
958        }
959
960        return FALSE;
961}
962
963static void
964handle_connection (DBusServer      *server,
965                   DBusConnection  *new_connection,
966                   void            *user_data)
967{
968        GdmSessionRelay *session_relay = GDM_SESSION_RELAY (user_data);
969
970        g_debug ("GdmSessionRelay: Handling new connection");
971
972        g_assert (session_relay->priv->session_connection == NULL);
973
974        if (session_relay->priv->session_connection == NULL) {
975                DBusObjectPathVTable vtable = { &session_relay_unregister_handler,
976                                                &session_relay_message_handler,
977                                                NULL, NULL, NULL, NULL
978                };
979
980                session_relay->priv->session_connection = new_connection;
981                dbus_connection_ref (new_connection);
982                dbus_connection_setup_with_g_main (new_connection, NULL);
983
984                g_debug ("GdmSessionRelay: session connection is %p", new_connection);
985
986                dbus_connection_add_filter (new_connection,
987                                            connection_filter_function,
988                                            session_relay,
989                                            NULL);
990
991                dbus_connection_set_unix_user_function (new_connection,
992                                                        allow_user_function,
993                                                        session_relay,
994                                                        NULL);
995
996                dbus_connection_register_object_path (new_connection,
997                                                      GDM_SESSION_RELAY_DBUS_PATH,
998                                                      &vtable,
999                                                      session_relay);
1000
1001                g_signal_emit (session_relay, signals[CONNECTED], 0);
1002        }
1003}
1004
1005gboolean
1006gdm_session_relay_start (GdmSessionRelay *session_relay)
1007{
1008        DBusError   error;
1009        gboolean    ret;
1010        char       *address;
1011        const char *auth_mechanisms[] = {"EXTERNAL", NULL};
1012
1013        ret = FALSE;
1014
1015        g_debug ("GdmSessionRelay: Creating D-Bus relay for session");
1016
1017        address = generate_address ();
1018
1019        dbus_error_init (&error);
1020        session_relay->priv->server = dbus_server_listen (address, &error);
1021        g_free (address);
1022
1023        if (session_relay->priv->server == NULL) {
1024                g_warning ("Cannot create D-BUS relay for the session: %s", error.message);
1025                /* FIXME: should probably fail if we can't create the socket */
1026                goto out;
1027        }
1028
1029        dbus_server_setup_with_g_main (session_relay->priv->server, NULL);
1030        dbus_server_set_auth_mechanisms (session_relay->priv->server, auth_mechanisms);
1031        dbus_server_set_new_connection_function (session_relay->priv->server,
1032                                                 handle_connection,
1033                                                 session_relay,
1034                                                 NULL);
1035        ret = TRUE;
1036
1037        g_free (session_relay->priv->server_address);
1038        session_relay->priv->server_address = dbus_server_get_address (session_relay->priv->server);
1039
1040        g_debug ("GdmSessionRelay: D-Bus relay listening on %s", session_relay->priv->server_address);
1041
1042 out:
1043
1044        return ret;
1045}
1046
1047gboolean
1048gdm_session_relay_stop (GdmSessionRelay *session_relay)
1049{
1050        gboolean ret;
1051
1052        ret = FALSE;
1053
1054        g_debug ("GdmSessionRelay: Stopping session relay...");
1055
1056        return ret;
1057}
1058
1059char *
1060gdm_session_relay_get_address (GdmSessionRelay *session_relay)
1061{
1062        return g_strdup (session_relay->priv->server_address);
1063}
1064
1065static void
1066gdm_session_relay_set_property (GObject      *object,
1067                                guint         prop_id,
1068                                const GValue *value,
1069                                GParamSpec   *pspec)
1070{
1071        switch (prop_id) {
1072        default:
1073                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1074                break;
1075        }
1076}
1077
1078static void
1079gdm_session_relay_get_property (GObject    *object,
1080                                guint       prop_id,
1081                                GValue     *value,
1082                                GParamSpec *pspec)
1083{
1084        switch (prop_id) {
1085        default:
1086                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1087                break;
1088        }
1089}
1090
1091static GObject *
1092gdm_session_relay_constructor (GType                  type,
1093                               guint                  n_construct_properties,
1094                               GObjectConstructParam *construct_properties)
1095{
1096        GdmSessionRelay      *session_relay;
1097
1098        session_relay = GDM_SESSION_RELAY (G_OBJECT_CLASS (gdm_session_relay_parent_class)->constructor (type,
1099                                                                                                            n_construct_properties,
1100                                                                                                            construct_properties));
1101
1102        return G_OBJECT (session_relay);
1103}
1104
1105static void
1106gdm_session_iface_init (GdmSessionIface *iface)
1107{
1108
1109        iface->open = gdm_session_relay_open;
1110        iface->setup = gdm_session_relay_setup;
1111        iface->setup_for_user = gdm_session_relay_setup_for_user;
1112        iface->authenticate = gdm_session_relay_authenticate;
1113        iface->authorize = gdm_session_relay_authorize;
1114        iface->accredit = gdm_session_relay_accredit;
1115        iface->close = gdm_session_relay_close;
1116
1117        iface->cancel = gdm_session_relay_cancel;
1118        iface->start_session = gdm_session_relay_start_session;
1119        iface->answer_query = gdm_session_relay_answer_query;
1120        iface->select_session = gdm_session_relay_select_session;
1121        iface->select_language = gdm_session_relay_select_language;
1122        iface->select_layout = gdm_session_relay_select_layout;
1123        iface->select_user = gdm_session_relay_select_user;
1124}
1125
1126static void
1127gdm_session_relay_class_init (GdmSessionRelayClass *klass)
1128{
1129        GObjectClass *object_class = G_OBJECT_CLASS (klass);
1130
1131        object_class->get_property = gdm_session_relay_get_property;
1132        object_class->set_property = gdm_session_relay_set_property;
1133        object_class->constructor = gdm_session_relay_constructor;
1134        object_class->finalize = gdm_session_relay_finalize;
1135
1136        g_type_class_add_private (klass, sizeof (GdmSessionRelayPrivate));
1137
1138        signals [CONNECTED] =
1139                g_signal_new ("connected",
1140                              G_OBJECT_CLASS_TYPE (object_class),
1141                              G_SIGNAL_RUN_FIRST,
1142                              G_STRUCT_OFFSET (GdmSessionRelayClass, connected),
1143                              NULL,
1144                              NULL,
1145                              g_cclosure_marshal_VOID__VOID,
1146                              G_TYPE_NONE,
1147                              0);
1148        signals [DISCONNECTED] =
1149                g_signal_new ("disconnected",
1150                              G_OBJECT_CLASS_TYPE (object_class),
1151                              G_SIGNAL_RUN_FIRST,
1152                              G_STRUCT_OFFSET (GdmSessionRelayClass, disconnected),
1153                              NULL,
1154                              NULL,
1155                              g_cclosure_marshal_VOID__VOID,
1156                              G_TYPE_NONE,
1157                              0);
1158}
1159
1160static void
1161gdm_session_relay_init (GdmSessionRelay *session_relay)
1162{
1163
1164        session_relay->priv = GDM_SESSION_RELAY_GET_PRIVATE (session_relay);
1165}
1166
1167static void
1168gdm_session_relay_finalize (GObject *object)
1169{
1170        GdmSessionRelay *session_relay;
1171
1172        g_return_if_fail (object != NULL);
1173        g_return_if_fail (GDM_IS_SESSION_RELAY (object));
1174
1175        session_relay = GDM_SESSION_RELAY (object);
1176
1177        g_return_if_fail (session_relay->priv != NULL);
1178
1179        gdm_session_relay_stop (session_relay);
1180
1181        G_OBJECT_CLASS (gdm_session_relay_parent_class)->finalize (object);
1182}
1183
1184GdmSessionRelay *
1185gdm_session_relay_new (void)
1186{
1187        GObject *object;
1188
1189        object = g_object_new (GDM_TYPE_SESSION_RELAY,
1190                               NULL);
1191
1192        return GDM_SESSION_RELAY (object);
1193}
Note: See TracBrowser for help on using the repository browser.