~ubuntu-branches/ubuntu/maverick/gnome-session/maverick

« back to all changes in this revision

Viewing changes to gnome-session/gsm-consolekit.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2009-05-08 19:54:30 UTC
  • mfrom: (1.2.4 upstream)
  • mto: This revision was merged to the branch mainline in revision 112.
  • Revision ID: james.westby@ubuntu.com-20090508195430-emwvafeu8f4upq97
Tags: upstream-2.26.1
ImportĀ upstreamĀ versionĀ 2.26.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <polkit-gnome/polkit-gnome.h>
36
36
#endif
37
37
 
 
38
#include "gsm-marshal.h"
38
39
#include "gsm-consolekit.h"
39
40
 
40
41
#define CK_NAME      "org.freedesktop.ConsoleKit"
64
65
 
65
66
enum {
66
67
        REQUEST_COMPLETED = 0,
 
68
        PRIVILEGES_COMPLETED,
67
69
        LAST_SIGNAL
68
70
};
69
71
 
133
135
                              G_TYPE_NONE,
134
136
                              1, G_TYPE_POINTER);
135
137
 
 
138
        signals [PRIVILEGES_COMPLETED] =
 
139
                g_signal_new ("privileges-completed",
 
140
                              G_OBJECT_CLASS_TYPE (object_class),
 
141
                              G_SIGNAL_RUN_LAST,
 
142
                              G_STRUCT_OFFSET (GsmConsolekitClass, privileges_completed),
 
143
                              NULL,
 
144
                              NULL,
 
145
                              gsm_marshal_VOID__BOOLEAN_BOOLEAN_POINTER,
 
146
                              G_TYPE_NONE,
 
147
                              3, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_POINTER);
 
148
 
136
149
        g_type_class_add_private (manager_class, sizeof (GsmConsolekitPrivate));
137
150
}
138
151
 
889
902
}
890
903
 
891
904
#ifdef HAVE_POLKIT_GNOME
892
 
static gboolean
893
 
gsm_consolekit_can_do_action (GsmConsolekit *manager,
894
 
                              const char    *action_id)
 
905
static PolKitResult
 
906
gsm_consolekit_get_result_for_action (GsmConsolekit *manager,
 
907
                                      const char    *action_id)
895
908
{
896
909
        PolKitGnomeContext *gnome_context;
897
910
        PolKitAction *action;
903
916
        gnome_context = polkit_gnome_context_get (NULL);
904
917
 
905
918
        if (gnome_context == NULL) {
906
 
                return FALSE;
 
919
                return POLKIT_RESULT_UNKNOWN;
907
920
        }
908
921
 
909
922
        if (gnome_context->pk_tracker == NULL) {
910
 
                return FALSE;
 
923
                return POLKIT_RESULT_UNKNOWN;
911
924
        }
912
925
 
913
926
        dbus_error_init (&dbus_error);
917
930
        dbus_error_free (&dbus_error);
918
931
 
919
932
        if (caller == NULL) {
920
 
                return FALSE;
 
933
                return POLKIT_RESULT_UNKNOWN;
921
934
        }
922
935
 
923
936
        action = polkit_action_new ();
924
937
        if (!polkit_action_set_action_id (action, action_id)) {
925
938
                polkit_action_unref (action);
926
939
                polkit_caller_unref (caller);
927
 
                return FALSE;
 
940
                return POLKIT_RESULT_UNKNOWN;
928
941
        }
929
942
 
930
 
        result = POLKIT_RESULT_UNKNOWN;
931
943
        error = NULL;
932
944
        result = polkit_context_is_caller_authorized (gnome_context->pk_context,
933
945
                                                      action, caller, FALSE,
936
948
                polkit_error_free (error);
937
949
        }
938
950
        polkit_action_unref (action);
939
 
                polkit_caller_unref (caller);
 
951
        polkit_caller_unref (caller);
 
952
 
 
953
        return result;
 
954
}
 
955
 
 
956
static gboolean
 
957
gsm_consolekit_can_do_action (GsmConsolekit *manager,
 
958
                              const char    *action_id)
 
959
{
 
960
        PolKitResult  result;
 
961
        gboolean      res;
 
962
        GError       *error;
 
963
 
 
964
        error = NULL;
 
965
        res = gsm_consolekit_ensure_ck_connection (manager, &error);
 
966
        if (!res) {
 
967
                g_warning ("Could not connect to ConsoleKit: %s",
 
968
                           error->message);
 
969
                g_error_free (error);
 
970
                return FALSE;
 
971
        }
 
972
 
 
973
        result = gsm_consolekit_get_result_for_action (manager, action_id);
940
974
 
941
975
        return result != POLKIT_RESULT_NO && result != POLKIT_RESULT_UNKNOWN;
942
976
}
943
 
#endif
 
977
 
 
978
static gboolean
 
979
gsm_consolekit_is_session_for_other_user (GsmConsolekit *manager,
 
980
                                          const char    *object_path,
 
981
                                          unsigned int   current_uid)
 
982
{
 
983
        DBusGProxy    *proxy;
 
984
        gboolean       res;
 
985
        char          *type;
 
986
        unsigned int   uid;
 
987
 
 
988
        proxy = dbus_g_proxy_new_for_name (manager->priv->dbus_connection,
 
989
                                           CK_NAME,
 
990
                                           object_path,
 
991
                                           CK_SESSION_INTERFACE);
 
992
 
 
993
        res = dbus_g_proxy_call_with_timeout (proxy,
 
994
                                              "GetUnixUser",
 
995
                                              INT_MAX,
 
996
                                              NULL,
 
997
                                              /* parameters: */
 
998
                                              G_TYPE_INVALID,
 
999
                                              /* return values: */
 
1000
                                              G_TYPE_UINT, &uid,
 
1001
                                              G_TYPE_INVALID);
 
1002
 
 
1003
        /* error is bad: we consider there's another user */
 
1004
        if (!res)
 
1005
                return TRUE;
 
1006
 
 
1007
        if (uid == current_uid)
 
1008
                return FALSE;
 
1009
 
 
1010
        /* filter out login sessions */
 
1011
        res = dbus_g_proxy_call_with_timeout (proxy,
 
1012
                                              "GetSessionType",
 
1013
                                              INT_MAX,
 
1014
                                              NULL,
 
1015
                                              /* parameters: */
 
1016
                                              G_TYPE_INVALID,
 
1017
                                              /* return values: */
 
1018
                                              G_TYPE_STRING, &type,
 
1019
                                              G_TYPE_INVALID);
 
1020
 
 
1021
        /* error is bad: we consider there's another user */
 
1022
        if (!res)
 
1023
                return TRUE;
 
1024
 
 
1025
        if (g_strcmp0 (type, GSM_CONSOLEKIT_SESSION_TYPE_LOGIN_WINDOW) == 0) {
 
1026
                g_free (type);
 
1027
                return FALSE;
 
1028
        }
 
1029
 
 
1030
        g_free (type);
 
1031
 
 
1032
        return TRUE;
 
1033
}
 
1034
 
 
1035
static gboolean
 
1036
gsm_consolekit_is_single_user (GsmConsolekit *manager)
 
1037
{
 
1038
        DBusGProxy   *proxy;
 
1039
        GError       *error;
 
1040
        gboolean      res;
 
1041
        gboolean      single;
 
1042
        GPtrArray    *array;
 
1043
        unsigned int  current_uid;
 
1044
        int           i;
 
1045
 
 
1046
        /* We use the same logic than the one used by ConsoleKit here -- it'd
 
1047
         * be nice to have a ConsoleKit API to help us, but well...
 
1048
         * If there's any error, we just assume it's multiple users. */
 
1049
 
 
1050
        proxy = dbus_g_proxy_new_for_name (manager->priv->dbus_connection,
 
1051
                                           CK_NAME,
 
1052
                                           CK_MANAGER_PATH,
 
1053
                                           CK_MANAGER_INTERFACE);
 
1054
 
 
1055
        error = NULL;
 
1056
        res = dbus_g_proxy_call_with_timeout (proxy,
 
1057
                                              "GetSessions",
 
1058
                                              INT_MAX,
 
1059
                                              &error,
 
1060
                                              /* parameters: */
 
1061
                                              G_TYPE_INVALID,
 
1062
                                              /* return values: */
 
1063
                                              dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &array,
 
1064
                                              G_TYPE_INVALID);
 
1065
 
 
1066
        if (!res) {
 
1067
                g_warning ("Unable to list sessions: %s", error->message);
 
1068
                g_error_free (error);
 
1069
                return FALSE;
 
1070
        }
 
1071
 
 
1072
        single = TRUE;
 
1073
        current_uid = getuid ();
 
1074
 
 
1075
        for (i = 0; i < array->len; i++) {
 
1076
                char *object_path;
 
1077
 
 
1078
                object_path = g_ptr_array_index (array, i);
 
1079
 
 
1080
                if (gsm_consolekit_is_session_for_other_user (manager,
 
1081
                                                              object_path,
 
1082
                                                              current_uid)) {
 
1083
                        single = FALSE;
 
1084
                        break;
 
1085
                }
 
1086
        }
 
1087
 
 
1088
        g_ptr_array_foreach (array, (GFunc) g_free, NULL);
 
1089
        g_ptr_array_free (array, TRUE);
 
1090
 
 
1091
        return single;
 
1092
}
 
1093
 
 
1094
static void
 
1095
obtain_privileges_cb (PolKitAction  *action,
 
1096
                      gboolean       gained_privilege,
 
1097
                      GError        *error,
 
1098
                      GsmConsolekit *manager)
 
1099
{
 
1100
        g_signal_emit (G_OBJECT (manager),
 
1101
                       signals [PRIVILEGES_COMPLETED],
 
1102
                       0, gained_privilege, FALSE, error);
 
1103
}
 
1104
 
 
1105
static gboolean
 
1106
gsm_consolekit_obtain_privileges_for_action (GsmConsolekit *manager,
 
1107
                                             const char    *action_id)
 
1108
{
 
1109
        PolKitAction *action;
 
1110
        pid_t         pid;
 
1111
        guint         xid;
 
1112
        gboolean      res;
 
1113
 
 
1114
        action = polkit_action_new ();
 
1115
        polkit_action_set_action_id (action, action_id);
 
1116
 
 
1117
        xid = 0;
 
1118
        pid = getpid ();
 
1119
 
 
1120
        res = polkit_gnome_auth_obtain (action,
 
1121
                                        xid,
 
1122
                                        pid,
 
1123
                                        (PolKitGnomeAuthCB) obtain_privileges_cb,
 
1124
                                        manager,
 
1125
                                        NULL);
 
1126
 
 
1127
        polkit_action_unref (action);
 
1128
 
 
1129
        return res;
 
1130
}
 
1131
 
 
1132
static gboolean
 
1133
gsm_consolekit_get_privileges_for_actions (GsmConsolekit *manager,
 
1134
                                           const char    *single_action_id,
 
1135
                                           const char    *multiple_action_id)
 
1136
{
 
1137
        PolKitResult  result;
 
1138
        gboolean      res;
 
1139
        GError       *error;
 
1140
        const char   *action_id;
 
1141
 
 
1142
        error = NULL;
 
1143
        res = gsm_consolekit_ensure_ck_connection (manager, &error);
 
1144
        if (!res) {
 
1145
                g_warning ("Could not connect to ConsoleKit: %s",
 
1146
                           error->message);
 
1147
                g_error_free (error);
 
1148
                return FALSE;
 
1149
        }
 
1150
 
 
1151
        if (gsm_consolekit_is_single_user (manager)) {
 
1152
                action_id = single_action_id;
 
1153
        } else {
 
1154
                action_id = multiple_action_id;
 
1155
        }
 
1156
 
 
1157
        result = gsm_consolekit_get_result_for_action (manager, action_id);
 
1158
 
 
1159
        switch (result) {
 
1160
        case POLKIT_RESULT_UNKNOWN:
 
1161
        case POLKIT_RESULT_NO:
 
1162
                return FALSE;
 
1163
        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
 
1164
        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
 
1165
        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
 
1166
        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
 
1167
        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
 
1168
        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
 
1169
                if (!gsm_consolekit_obtain_privileges_for_action (manager,
 
1170
                                                                  action_id)) {
 
1171
                        /* if the call doesn't work, then we were not even able
 
1172
                         * to do the call requesting the privileges: the setup
 
1173
                         * is likely broken */
 
1174
                        return FALSE;
 
1175
                }
 
1176
                break;
 
1177
        case POLKIT_RESULT_YES:
 
1178
                g_signal_emit (G_OBJECT (manager),
 
1179
                               signals [PRIVILEGES_COMPLETED],
 
1180
                               0, TRUE, FALSE, NULL);
 
1181
                break;
 
1182
        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
 
1183
        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
 
1184
                g_signal_emit (G_OBJECT (manager),
 
1185
                               signals [PRIVILEGES_COMPLETED],
 
1186
                               0, TRUE, TRUE, NULL);
 
1187
                break;
 
1188
        default:
 
1189
                g_assert_not_reached ();
 
1190
                break;
 
1191
        }
 
1192
 
 
1193
        return TRUE;
 
1194
}
 
1195
#endif
 
1196
 
 
1197
gboolean
 
1198
gsm_consolekit_get_restart_privileges (GsmConsolekit *manager)
 
1199
{
 
1200
#ifdef HAVE_POLKIT_GNOME
 
1201
        return gsm_consolekit_get_privileges_for_actions (manager,
 
1202
                                                          "org.freedesktop.consolekit.system.restart",
 
1203
                                                          "org.freedesktop.consolekit.system.restart-multiple-users");
 
1204
#else
 
1205
        g_debug ("GsmConsolekit: built without PolicyKit-gnome support");
 
1206
        return FALSE;
 
1207
#endif
 
1208
}
 
1209
 
 
1210
gboolean
 
1211
gsm_consolekit_get_stop_privileges (GsmConsolekit *manager)
 
1212
{
 
1213
#ifdef HAVE_POLKIT_GNOME
 
1214
        return gsm_consolekit_get_privileges_for_actions (manager,
 
1215
                                                          "org.freedesktop.consolekit.system.stop",
 
1216
                                                          "org.freedesktop.consolekit.system.stop-multiple-users");
 
1217
#else
 
1218
        g_debug ("GsmConsolekit: built without PolicyKit-gnome support");
 
1219
        return FALSE;
 
1220
#endif
 
1221
}
944
1222
 
945
1223
gboolean
946
1224
gsm_consolekit_can_restart (GsmConsolekit *manager)
947
1225
{
948
1226
#ifdef HAVE_POLKIT_GNOME
949
 
        gboolean res;
950
 
        GError  *error;
951
 
 
952
 
        error = NULL;
953
 
        res = gsm_consolekit_ensure_ck_connection (manager, &error);
954
 
        if (!res) {
955
 
                g_warning ("Could not connect to ConsoleKit: %s",
956
 
                           error->message);
957
 
                g_error_free (error);
958
 
                return FALSE;
959
 
        }
960
 
 
961
1227
        return gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.restart") ||
962
1228
               gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.restart-multiple-users");
963
1229
#else
970
1236
gsm_consolekit_can_stop (GsmConsolekit *manager)
971
1237
{
972
1238
#ifdef HAVE_POLKIT_GNOME
973
 
        gboolean res;
974
 
        GError  *error;
975
 
        error = NULL;
976
 
        res = gsm_consolekit_ensure_ck_connection (manager, &error);
977
 
        if (!res) {
978
 
                g_warning ("Could not connect to ConsoleKit: %s",
979
 
                           error->message);
980
 
                g_error_free (error);
981
 
                return FALSE;
982
 
        }
983
 
 
984
1239
        return gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.stop") ||
985
1240
               gsm_consolekit_can_do_action (manager, "org.freedesktop.consolekit.system.stop-multiple-users");
986
1241
#else