def _validatePath(path, perms): """Validate a disk image or other ifle. _validatePath makes sure that the user requesting a privileged operation would have permission to interact with the file in question. Args: disk: A path to a disk image perms: A bitmask composed of os.R_OK, os.W_OK, and/or os.X_OK Raises: debmarshal.errors.AccessDenied if the unprivileged user doesn't have permission to interact with the path using perms. """ # Start by setting the process uid to getCaller(). This is primarily # done to make sure we're respecting the abstraction introduced by # getCaller(). # # This won't guarantee that we have the necessary bits for, e.g., # AFS, where you need a separate token to prove your identity, but # it would work for most other cases. old_uid = os.getuid() os.setreuid(utils.getCaller(), 0) try: if not os.access(path, perms): raise errors.AccessDenied('UID %s does not have access to %s.' % (utils.getCaller(), path)) finally: # Reset the process uid that we changed earlier. os.setuid(old_uid)
def _validateNetwork(net, virt_con=None): """Validate a debmarshal network. This function checks that the network name passed in is a network known to (i.e. created by) debmarshal. It also verifies that the network was created by the user calling the function. Args: net: The name of the debmarshal network. virt_con: A read-only libvirt.virConnect instance. We'll open one of our own if one isn't passed in. Since libvirt network information is shared across all hypervisors, virt_con can be a connection to any libvirt driver. Raises: debmarshal.errors.NetworkNotFound if the named network doesn't exist. debmarshal.errors.AccessDenied if the network isn't owned by the caller. """ if not virt_con: virt_con = libvirt.open('qemu:///system') nets = networks.loadNetworkState(virt_con) if net not in nets: raise errors.NetworkNotFound("Network %s does not exist." % net) if nets[net] != utils.getCaller(): raise errors.AccessDenied("Network %s is not owned by UID %s." % (net, utils.getCaller()))
def testWrongUser(self): """Wrong user leads to an AcccessDenied exception.""" self.mox.StubOutWithMock(utils, 'getCaller') utils.getCaller().MultipleTimes().AndReturn(500) self.mox.ReplayAll() self.assertRaises(errors.AccessDenied, domains._validateNetwork, 'debmarshal-1', self.virt_con)
def testValidNetwork(self): """Valid network name from the right caller passes validation.""" self.mox.StubOutWithMock(utils, 'getCaller') utils.getCaller().MultipleTimes().AndReturn(500) self.mox.ReplayAll() # Once again, we want a self.assertNoRaises, or something, but it # doesn't exist, so we just run the code domains._validateNetwork('debmarshal-0', self.virt_con)
def testNoConnection(self): """_validateNetwork is able to open its own libvirt connection.""" self.mox.StubOutWithMock(libvirt, 'open') libvirt.open(mox.IgnoreArg()).AndReturn(self.virt_con) self.mox.StubOutWithMock(utils, 'getCaller') utils.getCaller().MultipleTimes().AndReturn(500) self.mox.ReplayAll() domains._validateNetwork('debmarshal-0')
def setUp(self): """Setup the getuid/setuid dance.""" super(TestValidatePath, self).setUp() self.mox.StubOutWithMock(os, 'getuid') self.mox.StubOutWithMock(os, 'setreuid') self.mox.StubOutWithMock(os, 'setuid') self.mox.StubOutWithMock(utils, 'getCaller') os.getuid().MultipleTimes().AndReturn(0) utils.getCaller().MultipleTimes().AndReturn(500) os.setreuid(500, 0) os.setuid(0)