Blob Blame History Raw
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jun 2020 16:23:14 -0400
Subject: [PATCH] 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 4a9a44e..a4f1d1d 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 84b9ebc..8522250 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 69384ce..0368dc9 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;