mgmt: implement mgmt.vm.property.Set

Sanitization of input value is tricky here, and also very important at
the same time. If property define value type (and it's something more
specific than 'str'), use that. Otherwise allow only printable ASCII
characters, and let appropriate event and setter handle value.
At this point I've reviewed all QubesVM properties in this category and
added appropriate setters where needed.

QubesOS/qubes-issues#2622
This commit is contained in:
Marek Marczykowski-Górecki 2017-03-12 01:25:22 +01:00
parent da51e6f032
commit 868dbeac3e
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -188,6 +188,53 @@ class QubesMgmt(object):
property_type,
str(value) if value is not None else '')
@asyncio.coroutine
def vm_property_set(self, untrusted_payload):
assert self.arg in self.dest.property_list()
property_def = self.dest.property_get_def(self.arg)
# do not treat type='str' as sufficient validation
if isinstance(property_def, qubes.vm.VMProperty):
try:
untrusted_vmname = untrusted_payload.decode('ascii')
except UnicodeDecodeError:
raise qubes.exc.QubesValueError
qubes.vm.qubesvm.validate_name(self.dest, property_def,
untrusted_vmname)
try:
newvalue = self.app.domains[untrusted_vmname]
except KeyError:
raise qubes.exc.QubesPropertyValueError(
self.dest, property_def, untrusted_vmname)
elif property_def.type is not None and property_def.type is not str:
if property_def.type is bool:
try:
untrusted_value = untrusted_payload.decode('ascii')
except UnicodeDecodeError:
raise qubes.exc.QubesValueError
newvalue = qubes.property.bool(None, None, untrusted_value)
else:
try:
newvalue = property_def.type(untrusted_payload)
except ValueError:
raise qubes.exc.QubesValueError
else:
# other types (including explicitly defined 'str') coerce to str
# with limited characters allowed
try:
untrusted_value = untrusted_payload.decode('ascii')
except UnicodeDecodeError:
raise qubes.exc.QubesValueError
allowed_set = string.printable
if not all(x in allowed_set for x in untrusted_value):
raise qubes.exc.QubesValueError(
'Invalid characters in property value')
newvalue = untrusted_value
self.fire_event_for_permission(newvalue=newvalue)
setattr(self.dest, self.arg, newvalue)
@asyncio.coroutine
def vm_property_help(self, untrusted_payload):
assert self.arg in self.dest.property_list()