Merge branch 'qubesd-socket'
* qubesd-socket: rpm: update dependency on qrexec Remove qubesd-query-fast Make qubesd connected directly as an socket qrexec service
This commit is contained in:
commit
aebb1594d7
4
Makefile
4
Makefile
@ -147,7 +147,6 @@ rpms-dom0:
|
|||||||
|
|
||||||
all:
|
all:
|
||||||
$(PYTHON) setup.py build
|
$(PYTHON) setup.py build
|
||||||
$(MAKE) -C qubes-rpc all
|
|
||||||
# Currently supported only on xen
|
# Currently supported only on xen
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@ -181,13 +180,12 @@ endif
|
|||||||
cp qubes-rpc/qubes.NotifyTools $(DESTDIR)/etc/qubes-rpc/
|
cp qubes-rpc/qubes.NotifyTools $(DESTDIR)/etc/qubes-rpc/
|
||||||
cp qubes-rpc/qubes.NotifyUpdates $(DESTDIR)/etc/qubes-rpc/
|
cp qubes-rpc/qubes.NotifyUpdates $(DESTDIR)/etc/qubes-rpc/
|
||||||
cp qubes-rpc/qubes.ConnectTCP $(DESTDIR)/etc/qubes-rpc/
|
cp qubes-rpc/qubes.ConnectTCP $(DESTDIR)/etc/qubes-rpc/
|
||||||
install qubes-rpc/qubesd-query-fast $(DESTDIR)/usr/libexec/qubes/
|
|
||||||
install -m 0755 qvm-tools/qubes-bug-report $(DESTDIR)/usr/bin/qubes-bug-report
|
install -m 0755 qvm-tools/qubes-bug-report $(DESTDIR)/usr/bin/qubes-bug-report
|
||||||
install -m 0755 qvm-tools/qubes-hcl-report $(DESTDIR)/usr/bin/qubes-hcl-report
|
install -m 0755 qvm-tools/qubes-hcl-report $(DESTDIR)/usr/bin/qubes-hcl-report
|
||||||
install -m 0755 qvm-tools/qvm-sync-clock $(DESTDIR)/usr/bin/qvm-sync-clock
|
install -m 0755 qvm-tools/qvm-sync-clock $(DESTDIR)/usr/bin/qvm-sync-clock
|
||||||
install -m 0755 qvm-tools/qvm-console-dispvm $(DESTDIR)/usr/bin/qvm-console-dispvm
|
install -m 0755 qvm-tools/qvm-console-dispvm $(DESTDIR)/usr/bin/qvm-console-dispvm
|
||||||
for method in $(ADMIN_API_METHODS_SIMPLE); do \
|
for method in $(ADMIN_API_METHODS_SIMPLE); do \
|
||||||
ln -s ../../usr/libexec/qubes/qubesd-query-fast \
|
ln -s ../../var/run/qubesd.sock \
|
||||||
$(DESTDIR)/etc/qubes-rpc/$$method || exit 1; \
|
$(DESTDIR)/etc/qubes-rpc/$$method || exit 1; \
|
||||||
done
|
done
|
||||||
install qubes-rpc/admin.vm.volume.Import $(DESTDIR)/etc/qubes-rpc/
|
install qubes-rpc/admin.vm.volume.Import $(DESTDIR)/etc/qubes-rpc/
|
||||||
|
1
qubes-rpc/.gitignore
vendored
1
qubes-rpc/.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
qfile-dom0-unpacker
|
qfile-dom0-unpacker
|
||||||
qubesd-query-fast
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
CFLAGS=-O2 -g -Wall -Werror -Wextra
|
|
||||||
|
|
||||||
all: qubesd-query-fast
|
|
||||||
|
|
||||||
qubesd-query-fast: qubesd-query-fast.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f qubesd-query-fast
|
|
@ -1,112 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define QUBESD_SOCKET "/var/run/qubesd.sock"
|
|
||||||
|
|
||||||
void write_wrapper(int fd, char *data, size_t len) {
|
|
||||||
size_t written = 0;
|
|
||||||
int ret;
|
|
||||||
while (written < len) {
|
|
||||||
ret = write(fd, data+written, len-written);
|
|
||||||
if (ret == -1) {
|
|
||||||
perror("write");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
written += ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
char *source_domain = getenv("QREXEC_REMOTE_DOMAIN");
|
|
||||||
char *target_domain = NULL;
|
|
||||||
char *target_domain_type = getenv("QREXEC_REQUESTED_TARGET_TYPE");
|
|
||||||
char *target_domain_name = getenv("QREXEC_REQUESTED_TARGET");
|
|
||||||
char *target_domain_keyword = getenv("QREXEC_REQUESTED_TARGET_KEYWORD");
|
|
||||||
char *service_name = strrchr(argv[0], '/');
|
|
||||||
int fd;
|
|
||||||
char buf[4096];
|
|
||||||
int read_ret;
|
|
||||||
struct sockaddr_un qubesd_addr = {
|
|
||||||
.sun_family = AF_UNIX,
|
|
||||||
.sun_path = QUBESD_SOCKET,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (service_name)
|
|
||||||
service_name++;
|
|
||||||
|
|
||||||
if (!source_domain || !target_domain_type || !service_name || argc > 2) {
|
|
||||||
fprintf(stderr, "Usage: %s [service-argument]\n", argv[0]);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "Expected environment variables:\n");
|
|
||||||
fprintf(stderr, " - QREXEC_REMOTE_DOMAIN - source domain for the call\n");
|
|
||||||
fprintf(stderr, " - QREXEC_REQUESTED_TARGET_TYPE - target domain for the call\n");
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "Additionally, this program assumes being called with desired service name as argv[0] (use symlink)\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (fd == -1) {
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *)&qubesd_addr, sizeof(qubesd_addr)) == -1) {
|
|
||||||
perror("connect to qubesd");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(target_domain_type, "keyword") == 0) {
|
|
||||||
// translate @adminvm back to dom0
|
|
||||||
if (strcmp(target_domain_keyword, "adminvm") == 0)
|
|
||||||
target_domain = "dom0";
|
|
||||||
else if (strcmp(target_domain_keyword, "default") == 0)
|
|
||||||
target_domain = "";
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Unsupported keyword: %s", target_domain_keyword);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
target_domain = target_domain_name;
|
|
||||||
|
|
||||||
assert(target_domain);
|
|
||||||
|
|
||||||
// write parameters, including trailing zero as separator
|
|
||||||
write_wrapper(fd, source_domain, strlen(source_domain) + 1);
|
|
||||||
write_wrapper(fd, service_name, strlen(service_name) + 1);
|
|
||||||
write_wrapper(fd, target_domain, strlen(target_domain) + 1);
|
|
||||||
if (argc == 2)
|
|
||||||
write_wrapper(fd, argv[1], strlen(argv[1]) + 1);
|
|
||||||
else
|
|
||||||
// empty argument
|
|
||||||
write_wrapper(fd, "\0", 1);
|
|
||||||
|
|
||||||
// now, read from stdin and write it to qubesd
|
|
||||||
while ((read_ret = read(0, buf, sizeof(buf))) > 0)
|
|
||||||
write_wrapper(fd, buf, read_ret);
|
|
||||||
|
|
||||||
if (read_ret == -1) {
|
|
||||||
perror("read from stdin");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// end of request, now let qubesd execute the action and return response
|
|
||||||
shutdown(fd, SHUT_WR);
|
|
||||||
|
|
||||||
// then, retrieve the response from qubesd and send it to stdout
|
|
||||||
while ((read_ret = read(fd, buf, sizeof(buf))) > 0)
|
|
||||||
write_wrapper(1, buf, read_ret);
|
|
||||||
|
|
||||||
if (read_ret == -1) {
|
|
||||||
perror("read from qubesd");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -252,8 +252,20 @@ class QubesDaemonProtocol(asyncio.Protocol):
|
|||||||
|
|
||||||
def eof_received(self):
|
def eof_received(self):
|
||||||
try:
|
try:
|
||||||
src, meth, dest, arg, untrusted_payload = \
|
connection_params, untrusted_payload = \
|
||||||
self.untrusted_buffer.getvalue().split(b'\0', 4)
|
self.untrusted_buffer.getvalue().split(b'\0', 1)
|
||||||
|
meth_arg, src, dest_type, dest = \
|
||||||
|
connection_params.split(b' ', 3)
|
||||||
|
if dest_type == b'keyword' and dest == b'adminvm':
|
||||||
|
dest_type, dest = b'name', b'dom0'
|
||||||
|
if dest_type != b'name':
|
||||||
|
raise ValueError(
|
||||||
|
'got {} destination type, '
|
||||||
|
'while only explicit name supported'.format(dest_type))
|
||||||
|
if b'+' in meth_arg:
|
||||||
|
meth, arg = meth_arg.split(b'+', 1)
|
||||||
|
else:
|
||||||
|
meth, arg = meth_arg, b''
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.log.warning('framing error')
|
self.app.log.warning('framing error')
|
||||||
self.transport.abort()
|
self.transport.abort()
|
||||||
|
@ -118,18 +118,18 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
super(TC_00_QubesDaemonProtocol, self).tearDown()
|
super(TC_00_QubesDaemonProtocol, self).tearDown()
|
||||||
|
|
||||||
def test_000_message_ok(self):
|
def test_000_message_ok(self):
|
||||||
self.writer.write(b'dom0\0mgmt.success\0dom0\0arg\0payload')
|
self.writer.write(b'mgmt.success+arg src name dest\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
asyncio.wait_for(self.reader.read(), 1))
|
asyncio.wait_for(self.reader.read(), 1))
|
||||||
self.assertEqual(response,
|
self.assertEqual(response,
|
||||||
b"0\0src: b'dom0', dest: b'dom0', arg: b'arg', payload: b'payload'")
|
b"0\0src: b'src', dest: b'dest', arg: b'arg', payload: b'payload'")
|
||||||
|
|
||||||
def test_001_message_ok_in_parts(self):
|
def test_001_message_ok_in_parts(self):
|
||||||
self.writer.write(b'dom0\0mgmt.')
|
self.writer.write(b'mgmt.success+arg')
|
||||||
self.loop.run_until_complete(self.writer.drain())
|
self.loop.run_until_complete(self.writer.drain())
|
||||||
self.writer.write(b'success\0dom0\0arg\0payload')
|
self.writer.write(b' dom0 name dom0\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
@ -138,7 +138,7 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
b"0\0src: b'dom0', dest: b'dom0', arg: b'arg', payload: b'payload'")
|
b"0\0src: b'dom0', dest: b'dom0', arg: b'arg', payload: b'payload'")
|
||||||
|
|
||||||
def test_002_message_ok_empty(self):
|
def test_002_message_ok_empty(self):
|
||||||
self.writer.write(b'dom0\0mgmt.success_none\0dom0\0arg\0payload')
|
self.writer.write(b'mgmt.success_none+arg dom0 name dom0\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
@ -146,7 +146,7 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
self.assertEqual(response, b"0\0")
|
self.assertEqual(response, b"0\0")
|
||||||
|
|
||||||
def test_003_exception_qubes(self):
|
def test_003_exception_qubes(self):
|
||||||
self.writer.write(b'dom0\0mgmt.qubesexception\0dom0\0arg\0payload')
|
self.writer.write(b'mgmt.qubesexception+arg dom0 name dom0\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
@ -154,7 +154,7 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
self.assertEqual(response, b"2\0QubesException\0\0qubes-exception\0")
|
self.assertEqual(response, b"2\0QubesException\0\0qubes-exception\0")
|
||||||
|
|
||||||
def test_004_exception_generic(self):
|
def test_004_exception_generic(self):
|
||||||
self.writer.write(b'dom0\0mgmt.exception\0dom0\0arg\0payload')
|
self.writer.write(b'mgmt.exception+arg dom0 name dom0\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
@ -162,7 +162,7 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
self.assertEqual(response, b"")
|
self.assertEqual(response, b"")
|
||||||
|
|
||||||
def test_005_event(self):
|
def test_005_event(self):
|
||||||
self.writer.write(b'dom0\0mgmt.event\0dom0\0arg\0payload')
|
self.writer.write(b'mgmt.event+arg dom0 name dom0\0payload')
|
||||||
self.writer.write_eof()
|
self.writer.write_eof()
|
||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
response = self.loop.run_until_complete(
|
response = self.loop.run_until_complete(
|
||||||
@ -174,3 +174,12 @@ class TC_00_QubesDaemonProtocol(qubes.tests.QubesTestCase):
|
|||||||
with self.assertNotRaises(asyncio.TimeoutError):
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
self.loop.run_until_complete(
|
self.loop.run_until_complete(
|
||||||
asyncio.wait_for(self.protocol.mgmt.task, 1))
|
asyncio.wait_for(self.protocol.mgmt.task, 1))
|
||||||
|
|
||||||
|
def test_006_target_adminvm(self):
|
||||||
|
self.writer.write(b'mgmt.success+arg src keyword adminvm\0payload')
|
||||||
|
self.writer.write_eof()
|
||||||
|
with self.assertNotRaises(asyncio.TimeoutError):
|
||||||
|
response = self.loop.run_until_complete(
|
||||||
|
asyncio.wait_for(self.reader.read(), 1))
|
||||||
|
self.assertEqual(response,
|
||||||
|
b"0\0src: b'src', dest: b'dom0', arg: b'arg', payload: b'payload'")
|
||||||
|
@ -83,8 +83,9 @@ def main(args=None):
|
|||||||
payload = sys.stdin.buffer.read() if args.payload else b''
|
payload = sys.stdin.buffer.read() if args.payload else b''
|
||||||
# pylint: enable=no-member
|
# pylint: enable=no-member
|
||||||
|
|
||||||
coro = asyncio.ensure_future(qubesd_client(args.socket, payload,
|
coro = asyncio.ensure_future(qubesd_client(
|
||||||
args.src, args.method, args.dest, args.arg))
|
args.socket, payload,
|
||||||
|
f'{args.method}+{args.arg} {args.src} name {args.dest}'))
|
||||||
|
|
||||||
for signame in ('SIGINT', 'SIGTERM'):
|
for signame in ('SIGINT', 'SIGTERM'):
|
||||||
loop.add_signal_handler(getattr(signal, signame),
|
loop.add_signal_handler(getattr(signal, signame),
|
||||||
|
@ -41,13 +41,11 @@ URL: http://www.qubes-os.org
|
|||||||
# /bin -> usr/bin symlink). python*.rpm provides only /usr/bin/python.
|
# /bin -> usr/bin symlink). python*.rpm provides only /usr/bin/python.
|
||||||
AutoReq: no
|
AutoReq: no
|
||||||
|
|
||||||
# FIXME: Enable this and disable debug_package
|
BuildArch: noarch
|
||||||
#BuildArch: noarch
|
|
||||||
|
|
||||||
BuildRequires: ImageMagick
|
BuildRequires: ImageMagick
|
||||||
BuildRequires: systemd-units
|
BuildRequires: systemd-units
|
||||||
BuildRequires: systemd
|
BuildRequires: systemd
|
||||||
BuildRequires: gcc
|
|
||||||
|
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
|
|
||||||
@ -76,7 +74,8 @@ Requires: libvirt-python3
|
|||||||
|
|
||||||
Requires: pciutils
|
Requires: pciutils
|
||||||
Requires: qubes-core-dom0-linux >= 4.0.11
|
Requires: qubes-core-dom0-linux >= 4.0.11
|
||||||
Requires: qubes-core-qrexec-dom0
|
# policy (daemon) using changed qubesd socket protocol
|
||||||
|
Requires: qubes-core-qrexec-dom0 >= 4.1.8
|
||||||
Requires: qubes-db-dom0
|
Requires: qubes-db-dom0
|
||||||
# TODO: R: qubes-gui-dom0 >= 2.1.11
|
# TODO: R: qubes-gui-dom0 >= 2.1.11
|
||||||
Conflicts: qubes-gui-dom0 < 1.1.13
|
Conflicts: qubes-gui-dom0 < 1.1.13
|
||||||
@ -504,7 +503,6 @@ done
|
|||||||
/usr/lib/qubes/cleanup-dispvms
|
/usr/lib/qubes/cleanup-dispvms
|
||||||
/usr/lib/qubes/fix-dir-perms.sh
|
/usr/lib/qubes/fix-dir-perms.sh
|
||||||
/usr/lib/qubes/startup-misc.sh
|
/usr/lib/qubes/startup-misc.sh
|
||||||
/usr/libexec/qubes/qubesd-query-fast
|
|
||||||
%{_unitdir}/lvm2-pvscan@.service.d/30_qubes.conf
|
%{_unitdir}/lvm2-pvscan@.service.d/30_qubes.conf
|
||||||
%{_unitdir}/qubes-core.service
|
%{_unitdir}/qubes-core.service
|
||||||
%{_unitdir}/qubes-qmemman.service
|
%{_unitdir}/qubes-qmemman.service
|
||||||
|
Loading…
Reference in New Issue
Block a user