Skip to content

Commit

Permalink
Working qrexec-policy-daemon
Browse files Browse the repository at this point in the history
Rewritten qrexec-daemon to use policy daemon instead of running
policy-exec separately for each call. If daemon fails, falls back
to old solution.

fixes QubesOS/qubes-issues#5125
  • Loading branch information
marmarta committed Aug 9, 2019
1 parent e97c5a6 commit aa0f3c8
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 4 deletions.
86 changes: 85 additions & 1 deletion daemon/qrexec-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define _GNU_SOURCE

#include <sys/select.h>
#include <stdio.h>
Expand All @@ -28,12 +29,17 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <err.h>
#include <string.h>
#include <assert.h>
#include "qrexec.h"
#include "libqrexec-utils.h"

#define QREXEC_MIN_VERSION QREXEC_PROTOCOL_V2
#define QREXEC_SOCKET_PATH "/var/run/qubes/policy.sock"


enum client_state {
CLIENT_INVALID = 0, // table slot not used
Expand Down Expand Up @@ -678,6 +684,73 @@ static void sanitize_name(char * untrusted_s_signed, char *extra_allowed_chars)
* Called when agent sends a message asking to execute a predefined command.
*/

static int connect_daemon_socket(
const int remote_domain_id,
const char *remote_domain_name,
const char *target_domain,
const char *service_name,
const struct service_params *request_id
) {
int result;
int command_size;
char response[32];
char *command;
int daemon_socket;
struct sockaddr_un daemon_socket_address = {
.sun_family = AF_UNIX,
.sun_path = QREXEC_SOCKET_PATH
};

daemon_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (daemon_socket < 0) {
perror("socket creation failed");
return -1;
}

result = connect(daemon_socket, (struct sockaddr *) &daemon_socket_address,
sizeof(daemon_socket_address));
if (result < 0) {
perror("connection to socket failed");
return -1;
}

command_size = asprintf(&command, "domain_id=%d\n"
"source=%s\n"
"intended_target=%s\n"
"service_and_arg=%s\n"
"process_ident=%s\n\n",
remote_domain_id, remote_domain_name, target_domain,
service_name, request_id->ident);
if (command_size < 0) {
perror("failed to construct request");
return -1;
}

result = send(daemon_socket, command, command_size, 0);
free(command);
if (result < 0) {
perror("send to socket failed");
return -1;
}

result = recv(daemon_socket, response, sizeof(response), 0);
if (result < 0) {
perror("error reading from socket");
return -1;
}
else {
if (!strncmp(response, "result=allow\n", sizeof("result=allow\n")-1)) {
return 0;
} else if (!strncmp(response, "result=deny\n", sizeof("result=deny\n")-1)) {
return 1;
} else {
warnx("invalid response");
return -1;
}
}
}


static void handle_execute_service(
const int remote_domain_id,
const char *remote_domain_name,
Expand All @@ -686,6 +759,7 @@ static void handle_execute_service(
const struct service_params *request_id)
{
int i;
int result;
int policy_pending_slot;
pid_t pid;
char remote_domain_id_str[10];
Expand All @@ -708,8 +782,17 @@ static void handle_execute_service(
policy_pending[policy_pending_slot].params = *request_id;
return;
}

result = connect_daemon_socket(remote_domain_id, remote_domain_name,
target_domain, service_name, request_id);
if (result >= 0) {
_exit(result);
} else {
warnx("invalid response");
}

for (i = 3; i < MAX_FDS; i++)
close(i);
close(i); /// should I do that?
signal(SIGCHLD, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
snprintf(remote_domain_id_str, sizeof(remote_domain_id_str), "%d",
Expand All @@ -725,6 +808,7 @@ static void handle_execute_service(
_exit(1);
}


static void handle_connection_terminated()
{
struct exec_params untrusted_params, params;
Expand Down
1 change: 1 addition & 0 deletions debian/qubes-core-qrexec.install
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ usr/bin/qrexec-fork-server
usr/bin/qrexec-policy-graph
usr/bin/qrexec-policy-restore
usr/bin/qrexec-policy-exec
usr/bin/qrexec-policy-daemon
usr/bin/qrexec-policy
usr/bin/qrexec-policy-agent
usr/bin/qubes-policy
Expand Down
11 changes: 8 additions & 3 deletions qrexec/tools/qrexec_policy_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#

import argparse
import datetime
import functools
import pathlib
import asyncio
Expand Down Expand Up @@ -90,15 +91,15 @@ async def handle_client_connection(log, policy_path, reader, writer):

result = handle_request(**args, log=log, path=policy_path)

writer.write(b"result=allow\n" if result else b"result=deny\n")
writer.write(b"result=deny\n" if result else b"result=allow\n")

await writer.drain()

finally:
writer.close()


async def main(args=None):
async def start_serving(args=None):
args = argparser.parse_args(args)

log = logging.getLogger('policy')
Expand All @@ -114,8 +115,12 @@ async def main(args=None):
await server.serve_forever()


def main(args=None):
asyncio.run(start_serving(args))


if __name__ == '__main__':
asyncio.run(main())
main()



3 changes: 3 additions & 0 deletions rpm_spec/qubes-qrexec.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ rm -f %{name}-%{version}
%{_bindir}/qrexec-policy-agent
%{_bindir}/qrexec-policy-graph
%{_bindir}/qrexec-policy-restore
%{_bindir}/qrexec-policy-daemon
%{_bindir}/qubes-policy
%{_bindir}/qrexec-policy

Expand Down Expand Up @@ -129,6 +130,7 @@ rm -f %{name}-%{version}
%{python3_sitelib}/qrexec/tools/qubes_policy.py
%{python3_sitelib}/qrexec/tools/qrexec_policy_agent.py
%{python3_sitelib}/qrexec/tools/qrexec_policy_exec.py
%{python3_sitelib}/qrexec/tools/qrexec_policy_daemon.py
%{python3_sitelib}/qrexec/tools/qrexec_policy_graph.py
%{python3_sitelib}/qrexec/tools/qrexec_policy_restore.py

Expand All @@ -141,6 +143,7 @@ rm -f %{name}-%{version}
%{python3_sitelib}/qrexec/tests/rpcconfirmation.py
%{python3_sitelib}/qrexec/tests/policy_api.py
%{python3_sitelib}/qrexec/tests/policy_parser.py
%{python3_sitelib}/qrexec/tests/qrexec_policy_daemon.py

%dir %{python3_sitelib}/qrexec/glade
%{python3_sitelib}/qrexec/glade/PolicyCreateConfirmationWindow.glade
Expand Down

0 comments on commit aa0f3c8

Please sign in to comment.