~artfwo/indicator-cpufreq/trunk

« back to all changes in this revision

Viewing changes to bin/indicator-cpufreq-selector

  • Committer: Артём Попов
  • Date: 2011-07-20 07:23:31 UTC
  • Revision ID: artfwo@gmail.com-20110720072331-bqgsdiku290x7ph6
Added policykit privilege checking from Jockey.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#! /usr/bin/env python
 
2
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
 
3
#
 
4
# Copyright (C) 2010 Артём Попов <artfwo@gmail.com>
 
5
# Copyright (C) 2008 Canonical Ltd.
 
6
#
 
7
# This program is free software: you can redistribute it and/or modify it 
 
8
# under the terms of the GNU General Public License version 3, as published 
 
9
# by the Free Software Foundation.
 
10
 
11
# This program is distributed in the hope that it will be useful, but 
 
12
# WITHOUT ANY WARRANTY; without even the implied warranties of 
 
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
14
# PURPOSE.  See the GNU General Public License for more details.
 
15
 
16
# You should have received a copy of the GNU General Public License along 
 
17
# with this program.  If not, see <http://www.gnu.org/licenses/>.
2
18
 
3
19
import gobject
4
20
 
7
23
 
8
24
from indicator_cpufreq import cpufreq
9
25
 
10
 
class IndicatorCpufreq(dbus.service.Object):
 
26
 
 
27
class PermissionDeniedByPolicy(dbus.DBusException):
 
28
    _dbus_error_name = 'com.ubuntu.DeviceDriver.PermissionDeniedByPolicy'
 
29
 
 
30
 
 
31
class IndicatorCpufreqSelector(dbus.service.Object):
 
32
 
 
33
    DBUS_INTERFACE_NAME = 'com.ubuntu.IndicatorCpufreqSelector'
 
34
    
11
35
    def __init__(self, bus, path):
12
36
        dbus.service.Object.__init__(self, bus, path)
13
 
 
14
 
    @dbus.service.method(dbus_interface='com.ubuntu.IndicatorCpufreqSelector',
15
 
        in_signature='', out_signature='b',
16
 
        sender_keyword='sender', connection_keyword='conn')
17
 
    def CanSet(self, sender=None, conn=None):
18
 
        return True
19
 
 
20
 
    @dbus.service.method(dbus_interface='com.ubuntu.IndicatorCpufreqSelector',
21
 
        in_signature='uu', out_signature='',
22
 
        sender_keyword='sender', connection_keyword='conn')
 
37
        
 
38
        # cached D-BUS interfaces for _check_polkit_privilege()
 
39
        self.dbus_info = None
 
40
        self.polkit = None
 
41
        self.main_loop = None
 
42
 
 
43
        self.enforce_polkit = True
 
44
        self._package_operation_in_progress = False
 
45
 
 
46
    @dbus.service.method(dbus_interface='com.ubuntu.IndicatorCpufreqSelector',
 
47
        in_signature='uu',
 
48
        out_signature='',
 
49
        sender_keyword='sender',
 
50
        connection_keyword='conn')
23
51
    def SetFrequency(self, cpu, frequency, sender=None, conn=None):
 
52
        self._check_polkit_privilege(sender, conn, 'com.ubuntu.indicatorcpufreq.setfrequencyscaling')
24
53
        error = cpufreq.set_frequency(cpu, frequency)
25
54
    
26
55
    @dbus.service.method(dbus_interface='com.ubuntu.IndicatorCpufreqSelector',
27
 
        in_signature='us', out_signature='',
28
 
        sender_keyword='sender', connection_keyword='conn')
 
56
        in_signature='us',
 
57
        out_signature='',
 
58
        sender_keyword='sender',
 
59
        connection_keyword='conn')
29
60
    def SetGovernor(self, cpu, governor, sender=None, conn=None):
 
61
        self._check_polkit_privilege(sender, conn, 'com.ubuntu.indicatorcpufreq.setfrequencyscaling')
30
62
        error = cpufreq.modify_policy_governor(cpu, governor)
31
63
    
 
64
    def _check_polkit_privilege(self, sender, conn, privilege):
 
65
        '''Verify that sender has a given PolicyKit privilege.
 
66
 
 
67
        sender is the sender's (private) D-BUS name, such as ":1:42"
 
68
        (sender_keyword in @dbus.service.methods). conn is
 
69
        the dbus.Connection object (connection_keyword in
 
70
        @dbus.service.methods). privilege is the PolicyKit privilege string.
 
71
 
 
72
        This method returns if the caller is privileged, and otherwise throws a
 
73
        PermissionDeniedByPolicy exception.
 
74
        '''
 
75
        if sender is None and conn is None:
 
76
            # called locally, not through D-BUS
 
77
            return
 
78
        if not self.enforce_polkit:
 
79
            # that happens for testing purposes when running on the session
 
80
            # bus, and it does not make sense to restrict operations here
 
81
            return
 
82
 
 
83
        # get peer PID
 
84
        if self.dbus_info is None:
 
85
            self.dbus_info = dbus.Interface(conn.get_object('org.freedesktop.DBus',
 
86
                '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus')
 
87
        pid = self.dbus_info.GetConnectionUnixProcessID(sender)
 
88
        
 
89
        # query PolicyKit
 
90
        if self.polkit is None:
 
91
            self.polkit = dbus.Interface(dbus.SystemBus().get_object(
 
92
                'org.freedesktop.PolicyKit1',
 
93
                '/org/freedesktop/PolicyKit1/Authority', False),
 
94
                'org.freedesktop.PolicyKit1.Authority')
 
95
        try:
 
96
            # we don't need is_challenge return here, since we call with AllowUserInteraction
 
97
            (is_auth, _, details) = self.polkit.CheckAuthorization(
 
98
                    ('unix-process', {'pid': dbus.UInt32(pid, variant_level=1),
 
99
                        'start-time': dbus.UInt64(0, variant_level=1)}), 
 
100
                    privilege, {'': ''}, dbus.UInt32(1), '', timeout=600)
 
101
        except dbus.DBusException as e:
 
102
            if e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown':
 
103
                # polkitd timed out, connect again
 
104
                self.polkit = None
 
105
                return self._check_polkit_privilege(sender, conn, privilege)
 
106
            else:
 
107
                raise
 
108
 
 
109
        if not is_auth:
 
110
            #logging.debug('_check_polkit_privilege: sender %s on connection %s pid %i is not authorized for %s: %s' %
 
111
            #        (sender, conn, pid, privilege, str(details)))
 
112
            raise PermissionDeniedByPolicy(privilege)
 
113
 
32
114
if __name__ == '__main__':
33
115
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
34
116
    
35
117
    bus = dbus.SystemBus()
36
118
    name = dbus.service.BusName("com.ubuntu.IndicatorCpufreqSelector", bus)
37
 
    object = IndicatorCpufreq(bus, '/Selector')
 
119
    object = IndicatorCpufreqSelector(bus, '/Selector')
 
120
    #object.enforce_polkit = False
38
121
 
39
122
    mainloop = gobject.MainLoop()
40
123
    mainloop.run()