qubes/tools/qubesd: add response header

QubesOS/qubes-issues#2622
This commit is contained in:
Wojtek Porczyk 2017-02-17 15:48:22 +01:00
parent 25d81b8ab6
commit 48f10a79c9
2 changed files with 46 additions and 4 deletions

View File

@ -72,7 +72,7 @@ variable-rgx=[a-z_][a-z0-9_]{2,30}$
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma # Good variable names which should always be accepted, separated by a comma
good-names=e,i,j,k,m,p,ex,Run,_,log,vm,xc,xs,ip,fd,fh,rw,st,tb,cb,ff good-names=e,i,j,k,m,p,v,ex,Run,_,log,vm,xc,xs,ip,fd,fh,rw,st,tb,cb,ff
# Bad variable names which should always be refused, separated by a comma # Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata bad-names=foo,bar,baz,toto,tutu,tata

View File

@ -5,6 +5,8 @@ import functools
import io import io
import os import os
import signal import signal
import struct
import traceback
import qubes import qubes
import qubes.libvirtaio import qubes.libvirtaio
@ -14,16 +16,17 @@ import qubes.vm.qubesvm
QUBESD_SOCK = '/var/run/qubesd.sock' QUBESD_SOCK = '/var/run/qubesd.sock'
class QubesDaemonProtocol(asyncio.Protocol): class QubesDaemonProtocol(asyncio.Protocol):
buffer_size = 65536 buffer_size = 65536
header = struct.Struct('!H')
def __init__(self, *args, app, **kwargs): def __init__(self, *args, app, debug=False, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.app = app self.app = app
self.untrusted_buffer = io.BytesIO() self.untrusted_buffer = io.BytesIO()
self.len_untrusted_buffer = 0 self.len_untrusted_buffer = 0
self.transport = None self.transport = None
self.debug = debug
def connection_made(self, transport): def connection_made(self, transport):
print('connection_made()') print('connection_made()')
@ -74,6 +77,12 @@ class QubesDaemonProtocol(asyncio.Protocol):
'with payload of %d bytes', 'with payload of %d bytes',
method, arg, src, dest, len(untrusted_payload)) method, arg, src, dest, len(untrusted_payload))
except qubes.exc.QubesException as err:
self.send_exception(err)
self.transport.write_eof()
self.transport.close()
return
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
self.app.log.exception( self.app.log.exception(
'unhandled exception while calling ' 'unhandled exception while calling '
@ -81,7 +90,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
src, method, dest, arg, len(untrusted_payload)) src, method, dest, arg, len(untrusted_payload))
else: else:
self.transport.write(response.encode('ascii')) self.send_response(response)
try: try:
self.transport.write_eof() self.transport.write_eof()
except NotImplementedError: except NotImplementedError:
@ -94,6 +103,39 @@ class QubesDaemonProtocol(asyncio.Protocol):
self.transport.abort() self.transport.abort()
def send_header(self, *args):
self.transport.write(self.header.pack(*args))
def send_response(self, content):
self.send_header(0x30)
self.transport.write(content.encode('utf-8'))
def send_event(self, subject, event, **kwargs):
self.send_header(0x31)
if subject is not self.app:
self.transport.write(subject.name.encode('ascii'))
self.transport.write(b'\0')
self.transport.write(event.encode('ascii') + b'\0')
for k, v in kwargs.items():
self.transport.write('{}\0{}\0'.format(k, str(v)).encode('ascii'))
self.transport.write(b'\0')
def send_exception(self, exc):
self.send_header(0x32)
self.transport.write(type(exc).__name__ + b'\0')
if self.debug:
self.transport.write(''.join(traceback.format_exception(
type(exc), exc, exc.__traceback__)).encode('utf-8'))
self.transport.write(b'\0')
self.transport.write(str(exc).encode('utf-8') + b'\0')
def sighandler(loop, signame, server): def sighandler(loop, signame, server):
print('caught {}, exiting'.format(signame)) print('caught {}, exiting'.format(signame))
server.close() server.close()