1 # -*- coding: utf-8 -*-
3 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
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.
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.
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
19 # Author: Stan Dolson , Goutam Kodu
34 from base.logger import *
36 from base.codes import *
37 from base import utils, device
45 # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters
46 # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04)
47 warnings.simplefilter("ignore", DeprecationWarning)
50 class AccessDeniedException(dbus.DBusException):
51 _dbus_error_name = 'com.hp.hplip.AccessDeniedException'
53 class UnsupportedException(dbus.DBusException):
54 _dbus_error_name = 'com.hp.hplip.UnsupportedException'
56 class UsageError(dbus.DBusException):
57 _dbus_error_name = 'com.hp.hplip.UsageError'
60 POLICY_KIT_ACTION = "com.hp.hplip"
61 INSTALL_PLUGIN_ACTION = "com.hp.hplip.installplugin"
64 def get_service_bus():
65 return dbus.SystemBus()
68 def get_service(bus=None):
70 bus = get_service_bus()
72 service = bus.get_object(BackendService.SERVICE_NAME, '/')
73 service = dbus.Interface(service, BackendService.INTERFACE_NAME)
77 class PolicyKitAuthentication(object):
79 super(PolicyKitAuthentication, self).__init__()
84 def is_authorized(self, action_id, pid=None):
88 pid = dbus.UInt32(pid)
90 authorized = self.policy_kit.IsProcessAuthorized(action_id, pid, False)
91 log.debug("is_authorized(%s) = %r" % (action_id, authorized))
93 return (authorized == 'yes')
96 def obtain_authorization(self, action_id, widget=None):
97 if self.is_authorized(action_id):
100 xid = (widget and widget.get_toplevel().window.xid or 0)
101 xid, pid = dbus.UInt32(xid), dbus.UInt32(os.getpid())
103 granted = self.auth_agent.ObtainAuthorization(action_id, xid, pid)
104 log.debug("obtain_authorization(%s) = %r" % (action_id, granted))
109 def get_policy_kit(self):
113 service = dbus.SystemBus().get_object('org.freedesktop.PolicyKit', '/')
114 self.pkit = dbus.Interface(service, 'org.freedesktop.PolicyKit')
117 policy_kit = property(get_policy_kit)
120 def get_auth_agent(self):
124 self.auth = dbus.SessionBus().get_object(
125 'org.freedesktop.PolicyKit.AuthenticationAgent', '/')
128 auth_agent = property(get_auth_agent)
132 class PolicyKitService(dbus.service.Object):
133 def check_permission_v0(self, sender, action=POLICY_KIT_ACTION):
135 log.error("Session not authorized by PolicyKit")
136 raise AccessDeniedException('Session not authorized by PolicyKit')
139 policy_auth = PolicyKitAuthentication()
140 bus = dbus.SystemBus()
142 dbus_object = bus.get_object('org.freedesktop.DBus', '/')
143 dbus_object = dbus.Interface(dbus_object, 'org.freedesktop.DBus')
145 pid = dbus.UInt32(dbus_object.GetConnectionUnixProcessID(sender))
147 granted = policy_auth.is_authorized(action, pid)
149 log.error("Process not authorized by PolicyKit")
150 raise AccessDeniedException('Process not authorized by PolicyKit')
152 granted = policy_auth.policy_kit.IsSystemBusNameAuthorized(action,
156 log.error("Session not authorized by PolicyKit version 0")
157 raise AccessDeniedException('Session not authorized by PolicyKit')
159 except AccessDeniedException:
160 log.warning("AccessDeniedException")
163 except dbus.DBusException, ex:
164 log.warning("AccessDeniedException %r", ex)
165 raise AccessDeniedException(ex.message)
168 def check_permission_v1(self, sender, connection, action=POLICY_KIT_ACTION):
169 if not sender or not connection:
170 log.error("Session not authorized by PolicyKit")
171 raise AccessDeniedException('Session not authorized by PolicyKit')
173 system_bus = dbus.SystemBus()
174 obj = system_bus.get_object("org.freedesktop.PolicyKit1",
175 "/org/freedesktop/PolicyKit1/Authority",
176 "org.freedesktop.PolicyKit1.Authority")
177 policy_kit = dbus.Interface(obj, "org.freedesktop.PolicyKit1.Authority")
178 info = dbus.Interface(connection.get_object("org.freedesktop.DBus",
179 "/org/freedesktop/DBus/Bus",
181 "org.freedesktop.DBus")
182 pid = info.GetConnectionUnixProcessID(sender)
186 { 'pid' : dbus.UInt32(pid, variant_level = 1) }
188 details = { '' : '' }
189 flags = dbus.UInt32(1) # AllowUserInteraction = 0x00000001
192 (ok, notused, details) = \
193 policy_kit.CheckAuthorization(subject,
199 log.error("Session not authorized by PolicyKit version 1")
204 if utils.to_bool(sys_conf.get('configure', 'policy-kit')):
205 class BackendService(PolicyKitService):
206 INTERFACE_NAME = 'com.hp.hplip'
207 SERVICE_NAME = 'com.hp.hplip'
208 LOGFILE_NAME = '/tmp/hp-pkservice.log'
210 def __init__(self, connection=None, path='/', logfile=LOGFILE_NAME):
211 if connection is None:
212 connection = get_service_bus()
214 super(BackendService, self).__init__(connection, path)
216 self.name = dbus.service.BusName(self.SERVICE_NAME, connection)
217 self.loop = gobject.MainLoop()
220 log.set_logfile("%s.%d" % (logfile, os.getpid()))
221 log.set_level("debug")
223 def run(self, version=None):
225 version = policykit_version()
227 log.error("Unable to determine installed PolicyKit version")
230 self.version = version
231 log.set_where(Logger.LOG_TO_CONSOLE_AND_FILE)
232 log.debug("Starting back-end service loop (version %d)" % version)
237 @dbus.service.method(dbus_interface=INTERFACE_NAME,
238 in_signature='s', out_signature='b',
239 sender_keyword='sender',
240 connection_keyword='connection')
241 def installPlugin(self, src_dir, sender=None, connection=None):
242 if self.version == 0:
244 self.check_permission_v0(sender, INSTALL_PLUGIN_ACTION)
245 except AccessDeniedException, e:
248 elif self.version == 1:
249 if not self.check_permission_v1(sender,
251 INSTALL_PLUGIN_ACTION):
255 log.error("installPlugin: invalid PolicyKit version %d" % self.version)
258 log.debug("installPlugin: installing from '%s'" % src_dir)
260 if not copyPluginFiles(src_dir):
261 log.error("Plugin installation failed")
267 @dbus.service.method(dbus_interface=INTERFACE_NAME,
268 in_signature='s', out_signature='b',
269 sender_keyword='sender',
270 connection_keyword='connection')
271 def shutdown(self, arg, sender=None, connection=None):
272 log.debug("Stopping backend service")
279 class PolicyKit(object):
280 def __init__(self, version=None):
282 version = policykit_version()
284 log.debug("Unable to determine installed PolicyKit version")
287 self.bus = dbus.SystemBus()
288 self.obj = self.bus.get_object(POLICY_KIT_ACTION, "/")
289 self.iface = dbus.Interface(self.obj, dbus_interface=POLICY_KIT_ACTION)
290 self.version = version
292 def installPlugin(self, src_dir):
293 if self.version == 0:
294 auth = PolicyKitAuthentication()
295 if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
296 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
300 ok = self.iface.installPlugin(src_dir)
302 except dbus.DBusException, e:
303 log.debug("installPlugin: %s" % str(e))
308 if self.version == 0:
309 auth = PolicyKitAuthentication()
310 if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
311 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
315 ok = self.iface.shutdown("")
317 except dbus.DBusException, e:
318 log.debug("shutdown: %s" % str(e))
323 def copyPluginFiles(src_dir):
326 plugin_spec = ConfigBase("plugin.spec")
327 products = plugin_spec.keys("products")
329 BITNESS = utils.getBitness()
330 ENDIAN = utils.getEndian()
331 PPDDIR = sys_conf.get('dirs', 'ppd')
332 DRVDIR = sys_conf.get('dirs', 'drv')
333 HOMEDIR = sys_conf.get('dirs', 'home')
334 DOCDIR = sys_conf.get('dirs', 'doc')
335 CUPSBACKENDDIR = sys_conf.get('dirs', 'cupsbackend')
336 CUPSFILTERDIR = sys_conf.get('dirs', 'cupsfilter')
337 RULESDIR = '/etc/udev/rules.d'
339 processor = utils.getProcessor()
340 if processor == 'power_machintosh':
343 ARCH = 'x86_%d' % BITNESS
346 SANELIBDIR = '/usr/lib64/sane'
347 LIBDIR = '/usr/lib64'
349 SANELIBDIR = '/usr/lib/sane'
354 for PRODUCT in products:
355 MODEL = PRODUCT.replace('hp-', '').replace('hp_', '')
356 for s in plugin_spec.get("products", PRODUCT).split(','):
358 if not plugin_spec.has_section(s):
359 log.error("Missing section [%s]" % s)
362 src = plugin_spec.get(s, 'src', '')
363 trg = plugin_spec.get(s, 'trg', '')
364 link = plugin_spec.get(s, 'link', '')
367 log.error("Missing 'src=' value in section [%s]" % s)
371 log.error("Missing 'trg=' value in section [%s]" % s)
374 src = os.path.basename(utils.cat(src))
378 link = utils.cat(link)
380 copies.append((src, trg, link))
382 copies = utils.uniqueList(copies)
387 for src, trg, link in copies:
389 if not os.path.exists(src):
390 log.debug("Source file %s does not exist. Skipping." % src)
393 if os.path.exists(trg):
394 log.debug("Target file %s already exists. Replacing." % trg)
397 trg_dir = os.path.dirname(trg)
399 if not os.path.exists(trg_dir):
400 log.debug("Target directory %s does not exist. Creating." % trg_dir)
401 os.makedirs(trg_dir, 0755)
403 if not os.path.isdir(trg_dir):
404 log.error("Target directory %s exists but is not a directory. Skipping." % trg_dir)
408 shutil.copyfile(src, trg)
409 except (IOError, OSError), e:
410 log.error("File copy failed: %s" % e.strerror)
414 if not os.path.exists(trg):
415 log.error("Target file %s does not exist. File copy failed." % trg)
418 os.chmod(trg, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH)
421 if os.path.exists(link):
422 log.debug("Symlink already exists. Replacing.")
425 log.debug("Creating symlink %s (link) to file %s (target)..." %
429 os.symlink(trg, link)
430 except (OSError, IOError), e:
431 log.debug("Unable to create symlink: %s" % e.strerror)
434 log.debug("Updating hplip.conf - installed = 1")
435 sys_state.set('plugin', "installed", '1')
436 log.debug("Updating hplip.conf - eula = 1")
437 sys_state.set('plugin', "eula", '1')
438 plugin_version = sys_conf.get('hplip', 'version', '0.0.0')
439 sys_state.set('plugin','version', plugin_version)
443 def run_plugin_command(required=True, plugin_reason=PLUGIN_REASON_NONE):
449 if utils.to_bool(sys_conf.get('configure', 'policy-kit')):
454 log.debug("Using PolicyKit for authentication")
455 except dbus.DBusException, ex:
456 log.error("PolicyKit NOT installed when configured for use")
458 if os.geteuid() == 0:
464 su_sudo = utils.su_sudo()
466 name,version,is_su = utils.os_release()
467 log.debug("name = %s version = %s is_su = %s" %(name,version,is_su))
468 if ( name == 'Fedora' and version >= '14' and is_su == True):
469 #using su opening GUI apps fail in Fedora 14.
470 #To run GUI apps as root, you need a root login shell (su -) in Fedora 14
471 su_sudo = 'su - -c "%s"'
473 su_sudo = 'su -c "%s"'
474 password_f = "get_password_ui"
476 log.error("Unable to find a suitable sudo command to run 'hp-plugin'")
477 return (False, False)
484 if utils.which("hp-plugin"):
487 p_path="python ./plugin.py"
489 if 'gksu' in su_sudo:
490 cmd = su_sudo % ("%s -u %s --reason %s" % (p_path, req, plugin_reason))
492 cmd += (" \"hp-plugin:- HP Device requires to install HP proprietary plugin. Please enter user (sudo) password to continue\"")
494 cmd = su_sudo % ("%s -u %s --reason %s To_install_plugin_for_HP_Device" % (p_path, req, plugin_reason))
496 log.debug("%s" % cmd)
497 if password_f is not None:
498 status, output = utils.run(cmd, log_output=True, password_func=password_f, timeout=1)
500 status, output = utils.run(cmd, log_output=True, password_func=None, timeout=1)
502 return (status == 0, True)
505 def policykit_version():
506 if os.path.isdir("/usr/share/polkit-1"):
508 elif os.path.isdir("/usr/share/PolicyKit"):