Blob Blame History Raw
From 3c525aa069dd52d85e3504e6179886a74aa14cd2 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jun 2020 16:23:14 -0400
Subject: [PATCH 03/42] Make 0.112 client and server work with the 113 protocol
 and vise versa

This makes the version of the sign API that takes a file type optional,
and makes the client attempt to negotiate which version it's getting.
It also leaves the server able to still handle the version from before
the file type was added.

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 src/client.c | 74 +++++++++++++++++++++++++++++++++++++---------------
 src/daemon.c | 63 +++++++++++++++++++++++++++++---------------
 src/daemon.h |  2 ++
 3 files changed, 97 insertions(+), 42 deletions(-)

diff --git a/src/client.c b/src/client.c
index 4a9a44e915c..a4f1d1dbbe7 100644
--- a/src/client.c
+++ b/src/client.c
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 #include <popt.h>
 #include <pwd.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/socket.h>
@@ -96,8 +97,8 @@ connect_to_server(void)
 static int32_t
 check_response(int sd, char **srvmsg);
 
-static void
-check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
+static int
+check_cmd_version(int sd, uint32_t command, char *name, int32_t version, bool do_exit)
 {
 	struct msghdr msg;
 	struct iovec iov[1];
@@ -116,7 +117,7 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
 	ssize_t n;
 	n = sendmsg(sd, &msg, 0);
 	if (n < 0) {
-		fprintf(stderr, "check-cmd-version: kill daemon failed: %m\n");
+		fprintf(stderr, "check-cmd-version: sendmsg failed: %m\n");
 		exit(1);
 	}
 
@@ -132,11 +133,17 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
 
 	char *srvmsg = NULL;
 	int32_t rc = check_response(sd, &srvmsg);
-	if (rc < 0)
+
+	if (do_exit && rc < 0)
 		errx(1, "command \"%s\" not known by server", name);
-	if (rc != version)
+
+	if (do_exit && rc != version)
 		errx(1, "command \"%s\": client version %d, server version %d",
 			name, version, rc);
+
+	if (rc < 0)
+		return rc;
+	return rc == version;
 }
 
 static void
@@ -146,7 +153,7 @@ send_kill_daemon(int sd)
 	struct iovec iov;
 	pesignd_msghdr pm;
 
-	check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0);
+	check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0, true);
 
 	pm.version = PESIGND_VERSION;
 	pm.command = CMD_KILL_DAEMON;
@@ -288,7 +295,7 @@ unlock_token(int sd, char *tokenname, char *pin)
 
 	uint32_t size1 = pesignd_string_size(pin);
 
-	check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0);
+	check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0, true);
 
 	pm.version = PESIGND_VERSION;
 	pm.command = CMD_UNLOCK_TOKEN;
@@ -365,7 +372,7 @@ is_token_unlocked(int sd, char *tokenname)
 
 	uint32_t size0 = pesignd_string_size(tokenname);
 
-	check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0);
+	check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0, true);
 
 	pm.version = PESIGND_VERSION;
 	pm.command = CMD_IS_TOKEN_UNLOCKED;
@@ -464,6 +471,9 @@ static void
 sign(int sd, char *infile, char *outfile, char *tokenname, char *certname,
 	int attached, uint32_t format)
 {
+	int rc;
+	bool add_file_type;
+
 	int infd = open(infile, O_RDONLY);
 	if (infd < 0) {
 		fprintf(stderr, "pesign-client: could not open input file "
@@ -493,12 +503,28 @@ oom:
 		exit(1);
 	}
 
-	check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED,
-			attached ? "sign-attached" : "sign-detached", 0);
+	rc = check_cmd_version(sd,
+			       attached ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE
+					: CMD_SIGN_DETACHED_WITH_FILE_TYPE,
+			       attached ? "sign-attached" : "sign-detached",
+			       0, format == FORMAT_KERNEL_MODULE);
+	if (rc >= 0) {
+		add_file_type = true;
+	} else {
+		add_file_type = false;
+		check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED
+					       : CMD_SIGN_DETACHED,
+				  attached ? "sign-attached" : "sign-detached",
+				  0, true);
+	}
 
+	printf("add_file_type:%d\n", add_file_type);
 	pm->version = PESIGND_VERSION;
-	pm->command = attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED;
-	pm->size = size0 + size1 + sizeof(format);
+	pm->command = attached ? (add_file_type ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE
+						: CMD_SIGN_ATTACHED)
+			       : (add_file_type ? CMD_SIGN_DETACHED_WITH_FILE_TYPE
+						: CMD_SIGN_DETACHED);
+	pm->size = size0 + size1 + (add_file_type ? sizeof(format) : 0);
 	iov[0].iov_base = pm;
 	iov[0].iov_len = sizeof (*pm);
 
@@ -515,25 +541,31 @@ oom:
 	}
 
 	char *buffer;
-	buffer = malloc(size0 + size1);
+	buffer = malloc(pm->size);
 	if (!buffer)
 		goto oom;
 
-	iov[0].iov_base = &format;
-	iov[0].iov_len = sizeof(format);
+	int pos = 0;
+
+	if (add_file_type) {
+		iov[pos].iov_base = &format;
+		iov[pos].iov_len = sizeof(format);
+		pos++;
+	}
 
 	pesignd_string *tn = (pesignd_string *)buffer;
 	pesignd_string_set(tn, tokenname);
-	iov[1].iov_base = tn;
-	iov[1].iov_len = size0;
+	iov[pos].iov_base = tn;
+	iov[pos].iov_len = size0;
+	pos++;
 
 	pesignd_string *cn = pesignd_string_next(tn);
 	pesignd_string_set(cn, certname);
-	iov[2].iov_base = cn;
-	iov[2].iov_len = size1;
+	iov[pos].iov_base = cn;
+	iov[pos].iov_len = size1;
 
 	msg.msg_iov = iov;
-	msg.msg_iovlen = 3;
+	msg.msg_iovlen = add_file_type ? 3 : 2;
 
 	n = sendmsg(sd, &msg, 0);
 	if (n < 0) {
@@ -547,7 +579,7 @@ oom:
 	send_fd(sd, outfd);
 
 	char *srvmsg = NULL;
-	int rc = check_response(sd, &srvmsg);
+	rc = check_response(sd, &srvmsg);
 	if (rc < 0) {
 		fprintf(stderr, "pesign-client: signing failed: \"%s\"\n",
 			srvmsg);
diff --git a/src/daemon.c b/src/daemon.c
index 84b9ebcb13f..8522250c2b4 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -25,6 +25,7 @@
 #include <poll.h>
 #include <pwd.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -569,7 +570,7 @@ out:
 
 static void
 handle_signing(context *ctx, struct pollfd *pollfd, socklen_t size,
-	int attached)
+	       int attached, bool with_file_type)
 {
 	struct msghdr msg;
 	struct iovec iov;
@@ -593,8 +594,12 @@ oom:
 
 	n = recvmsg(pollfd->fd, &msg, MSG_WAITALL);
 
-	file_format = *((uint32_t *) buffer);
-	n -= sizeof(uint32_t);
+	if (with_file_type) {
+		file_format = *((uint32_t *) buffer);
+		n -= sizeof(uint32_t);
+	} else {
+		file_format = FORMAT_PE_BINARY;
+	}
 
 	pesignd_string *tn = (pesignd_string *)(buffer + sizeof(uint32_t));
 	if (n < (long long)sizeof(tn->size)) {
@@ -674,34 +679,44 @@ finish:
 	teardown_digests(ctx->cms);
 }
 
+static inline void
+handle_sign_helper(context *ctx, struct pollfd *pollfd, socklen_t size,
+		   int attached, bool with_file_type)
+{
+	int rc = cms_context_alloc(&ctx->cms);
+	if (rc < 0)
+		return;
+
+	steal_from_cms(ctx->backup_cms, ctx->cms);
+
+	handle_signing(ctx, pollfd, size, attached, with_file_type);
+
+	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
+	cms_context_fini(ctx->cms);
+}
+
 static void
 handle_sign_attached(context *ctx, struct pollfd *pollfd, socklen_t size)
 {
-	int rc = cms_context_alloc(&ctx->cms);
-	if (rc < 0)
-		return;
+	handle_sign_helper(ctx, pollfd, size, 1, false);
+}
 
-	steal_from_cms(ctx->backup_cms, ctx->cms);
-
-	handle_signing(ctx, pollfd, size, 1);
-
-	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
-	cms_context_fini(ctx->cms);
+static void
+handle_sign_attached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size)
+{
+	handle_sign_helper(ctx, pollfd, size, 1, true);
 }
 
 static void
 handle_sign_detached(context *ctx, struct pollfd *pollfd, socklen_t size)
 {
-	int rc = cms_context_alloc(&ctx->cms);
-	if (rc < 0)
-		return;
+	handle_sign_helper(ctx, pollfd, size, 0, false);
+}
 
-	steal_from_cms(ctx->backup_cms, ctx->cms);
-
-	handle_signing(ctx, pollfd, size, 0);
-
-	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
-	cms_context_fini(ctx->cms);
+static void
+handle_sign_detached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size)
+{
+	handle_sign_helper(ctx, pollfd, size, 0, true);
 }
 
 static void
@@ -733,6 +748,12 @@ cmd_table_t cmd_table[] = {
 		{ CMD_UNLOCK_TOKEN, handle_unlock_token, "unlock-token", 0 },
 		{ CMD_SIGN_ATTACHED, handle_sign_attached, "sign-attached", 0 },
 		{ CMD_SIGN_DETACHED, handle_sign_detached, "sign-detached", 0 },
+		{ CMD_SIGN_ATTACHED_WITH_FILE_TYPE,
+		  handle_sign_attached_with_file_type,
+		  "sign-attached-with-file-type", 0 },
+		{ CMD_SIGN_DETACHED_WITH_FILE_TYPE,
+		  handle_sign_detached_with_file_type,
+		  "sign-detached-with-file-type", 0 },
 		{ CMD_RESPONSE, NULL, "response",  0 },
 		{ CMD_IS_TOKEN_UNLOCKED, handle_is_token_unlocked,
 			"is-token-unlocked", 0 },
diff --git a/src/daemon.h b/src/daemon.h
index 69384ce775c..0368dc9256c 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -45,6 +45,8 @@ typedef enum {
 	CMD_RESPONSE,
 	CMD_IS_TOKEN_UNLOCKED,
 	CMD_GET_CMD_VERSION,
+	CMD_SIGN_ATTACHED_WITH_FILE_TYPE,
+	CMD_SIGN_DETACHED_WITH_FILE_TYPE,
 	CMD_LIST_END
 } pesignd_cmd;
 
-- 
2.29.2