edca44f
From 84547e6b7173e4b10a1931fd25f329ea9a8f68b0 Mon Sep 17 00:00:00 2001
edca44f
From: Peter Jones <pjones@redhat.com>
edca44f
Date: Thu, 11 Jun 2020 16:23:14 -0400
edca44f
Subject: [PATCH] Make 0.112 client and server work with the 113 protocol and
edca44f
 vise versa
edca44f
edca44f
This makes the version of the sign API that takes a file type optional,
edca44f
and makes the client attempt to negotiate which version it's getting.
edca44f
It also leaves the server able to still handle the version from before
edca44f
the file type was added.
edca44f
edca44f
Signed-off-by: Peter Jones <pjones@redhat.com>
edca44f
---
edca44f
 src/client.c | 74 +++++++++++++++++++++++++++++++++++++---------------
edca44f
 src/daemon.c | 63 +++++++++++++++++++++++++++++---------------
edca44f
 src/daemon.h |  2 ++
edca44f
 3 files changed, 97 insertions(+), 42 deletions(-)
edca44f
edca44f
diff --git a/src/client.c b/src/client.c
edca44f
index aa373abd981..57bcc09cbe8 100644
edca44f
--- a/src/client.c
edca44f
+++ b/src/client.c
edca44f
@@ -11,6 +11,7 @@
edca44f
 #include <fcntl.h>
edca44f
 #include <popt.h>
edca44f
 #include <pwd.h>
edca44f
+#include <stdbool.h>
edca44f
 #include <stddef.h>
edca44f
 #include <stdlib.h>
edca44f
 #include <sys/socket.h>
edca44f
@@ -84,8 +85,8 @@ connect_to_server(void)
edca44f
 static int32_t
edca44f
 check_response(int sd, char **srvmsg);
edca44f
 
edca44f
-static void
edca44f
-check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
edca44f
+static int
edca44f
+check_cmd_version(int sd, uint32_t command, char *name, int32_t version, bool do_exit)
edca44f
 {
edca44f
 	struct msghdr msg;
edca44f
 	struct iovec iov[1];
edca44f
@@ -104,7 +105,7 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
edca44f
 	ssize_t n;
edca44f
 	n = sendmsg(sd, &msg, 0);
edca44f
 	if (n < 0) {
edca44f
-		fprintf(stderr, "check-cmd-version: kill daemon failed: %m\n");
edca44f
+		fprintf(stderr, "check-cmd-version: sendmsg failed: %m\n");
edca44f
 		exit(1);
edca44f
 	}
edca44f
 
edca44f
@@ -120,11 +121,17 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version)
edca44f
 
edca44f
 	char *srvmsg = NULL;
edca44f
 	int32_t rc = check_response(sd, &srvmsg);
edca44f
-	if (rc < 0)
edca44f
+
edca44f
+	if (do_exit && rc < 0)
edca44f
 		errx(1, "command \"%s\" not known by server", name);
edca44f
-	if (rc != version)
edca44f
+
edca44f
+	if (do_exit && rc != version)
edca44f
 		errx(1, "command \"%s\": client version %d, server version %d",
edca44f
 			name, version, rc);
edca44f
+
edca44f
+	if (rc < 0)
edca44f
+		return rc;
edca44f
+	return rc == version;
edca44f
 }
edca44f
 
edca44f
 static void
edca44f
@@ -134,7 +141,7 @@ send_kill_daemon(int sd)
edca44f
 	struct iovec iov;
edca44f
 	pesignd_msghdr pm;
edca44f
 
edca44f
-	check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0);
edca44f
+	check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0, true);
edca44f
 
edca44f
 	pm.version = PESIGND_VERSION;
edca44f
 	pm.command = CMD_KILL_DAEMON;
edca44f
@@ -276,7 +283,7 @@ unlock_token(int sd, char *tokenname, char *pin)
edca44f
 
edca44f
 	uint32_t size1 = pesignd_string_size(pin);
edca44f
 
edca44f
-	check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0);
edca44f
+	check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0, true);
edca44f
 
edca44f
 	pm.version = PESIGND_VERSION;
edca44f
 	pm.command = CMD_UNLOCK_TOKEN;
edca44f
@@ -353,7 +360,7 @@ is_token_unlocked(int sd, char *tokenname)
edca44f
 
edca44f
 	uint32_t size0 = pesignd_string_size(tokenname);
edca44f
 
edca44f
-	check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0);
edca44f
+	check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0, true);
edca44f
 
edca44f
 	pm.version = PESIGND_VERSION;
edca44f
 	pm.command = CMD_IS_TOKEN_UNLOCKED;
edca44f
@@ -452,6 +459,9 @@ static void
edca44f
 sign(int sd, char *infile, char *outfile, char *tokenname, char *certname,
edca44f
 	int attached, uint32_t format)
edca44f
 {
edca44f
+	int rc;
edca44f
+	bool add_file_type;
edca44f
+
edca44f
 	int infd = open(infile, O_RDONLY);
edca44f
 	if (infd < 0) {
edca44f
 		fprintf(stderr, "pesign-client: could not open input file "
edca44f
@@ -481,12 +491,28 @@ oom:
edca44f
 		exit(1);
edca44f
 	}
edca44f
 
edca44f
-	check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED,
edca44f
-			attached ? "sign-attached" : "sign-detached", 0);
edca44f
+	rc = check_cmd_version(sd,
edca44f
+			       attached ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE
edca44f
+					: CMD_SIGN_DETACHED_WITH_FILE_TYPE,
edca44f
+			       attached ? "sign-attached" : "sign-detached",
edca44f
+			       0, format == FORMAT_KERNEL_MODULE);
edca44f
+	if (rc >= 0) {
edca44f
+		add_file_type = true;
edca44f
+	} else {
edca44f
+		add_file_type = false;
edca44f
+		check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED
edca44f
+					       : CMD_SIGN_DETACHED,
edca44f
+				  attached ? "sign-attached" : "sign-detached",
edca44f
+				  0, true);
edca44f
+	}
edca44f
 
edca44f
+	printf("add_file_type:%d\n", add_file_type);
edca44f
 	pm->version = PESIGND_VERSION;
edca44f
-	pm->command = attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED;
edca44f
-	pm->size = size0 + size1 + sizeof(format);
edca44f
+	pm->command = attached ? (add_file_type ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE
edca44f
+						: CMD_SIGN_ATTACHED)
edca44f
+			       : (add_file_type ? CMD_SIGN_DETACHED_WITH_FILE_TYPE
edca44f
+						: CMD_SIGN_DETACHED);
edca44f
+	pm->size = size0 + size1 + (add_file_type ? sizeof(format) : 0);
edca44f
 	iov[0].iov_base = pm;
edca44f
 	iov[0].iov_len = sizeof (*pm);
edca44f
 
edca44f
@@ -503,25 +529,31 @@ oom:
edca44f
 	}
edca44f
 
edca44f
 	char *buffer;
edca44f
-	buffer = malloc(size0 + size1);
edca44f
+	buffer = malloc(pm->size);
edca44f
 	if (!buffer)
edca44f
 		goto oom;
edca44f
 
edca44f
-	iov[0].iov_base = &format;
edca44f
-	iov[0].iov_len = sizeof(format);
edca44f
+	int pos = 0;
edca44f
+
edca44f
+	if (add_file_type) {
edca44f
+		iov[pos].iov_base = &format;
edca44f
+		iov[pos].iov_len = sizeof(format);
edca44f
+		pos++;
edca44f
+	}
edca44f
 
edca44f
 	pesignd_string *tn = (pesignd_string *)buffer;
edca44f
 	pesignd_string_set(tn, tokenname);
edca44f
-	iov[1].iov_base = tn;
edca44f
-	iov[1].iov_len = size0;
edca44f
+	iov[pos].iov_base = tn;
edca44f
+	iov[pos].iov_len = size0;
edca44f
+	pos++;
edca44f
 
edca44f
 	pesignd_string *cn = pesignd_string_next(tn);
edca44f
 	pesignd_string_set(cn, certname);
edca44f
-	iov[2].iov_base = cn;
edca44f
-	iov[2].iov_len = size1;
edca44f
+	iov[pos].iov_base = cn;
edca44f
+	iov[pos].iov_len = size1;
edca44f
 
edca44f
 	msg.msg_iov = iov;
edca44f
-	msg.msg_iovlen = 3;
edca44f
+	msg.msg_iovlen = add_file_type ? 3 : 2;
edca44f
 
edca44f
 	n = sendmsg(sd, &msg, 0);
edca44f
 	if (n < 0) {
edca44f
@@ -535,7 +567,7 @@ oom:
edca44f
 	send_fd(sd, outfd);
edca44f
 
edca44f
 	char *srvmsg = NULL;
edca44f
-	int rc = check_response(sd, &srvmsg);
edca44f
+	rc = check_response(sd, &srvmsg);
edca44f
 	if (rc < 0) {
edca44f
 		fprintf(stderr, "pesign-client: signing failed: \"%s\"\n",
edca44f
 			srvmsg);
edca44f
diff --git a/src/daemon.c b/src/daemon.c
edca44f
index 9374d59be30..494beb9af72 100644
edca44f
--- a/src/daemon.c
edca44f
+++ b/src/daemon.c
edca44f
@@ -12,6 +12,7 @@
edca44f
 #include <poll.h>
edca44f
 #include <pwd.h>
edca44f
 #include <signal.h>
edca44f
+#include <stdbool.h>
edca44f
 #include <stdlib.h>
edca44f
 #include <stdio.h>
edca44f
 #include <string.h>
edca44f
@@ -561,7 +562,7 @@ out:
edca44f
 
edca44f
 static void
edca44f
 handle_signing(context *ctx, struct pollfd *pollfd, socklen_t size,
edca44f
-	int attached)
edca44f
+	       int attached, bool with_file_type)
edca44f
 {
edca44f
 	struct msghdr msg;
edca44f
 	struct iovec iov;
edca44f
@@ -585,8 +586,12 @@ oom:
edca44f
 
edca44f
 	n = recvmsg(pollfd->fd, &msg, MSG_WAITALL);
edca44f
 
edca44f
-	file_format = *((uint32_t *) buffer);
edca44f
-	n -= sizeof(uint32_t);
edca44f
+	if (with_file_type) {
edca44f
+		file_format = *((uint32_t *) buffer);
edca44f
+		n -= sizeof(uint32_t);
edca44f
+	} else {
edca44f
+		file_format = FORMAT_PE_BINARY;
edca44f
+	}
edca44f
 
edca44f
 	pesignd_string *tn = (pesignd_string *)(buffer + sizeof(uint32_t));
edca44f
 	if (n < (long long)sizeof(tn->size)) {
edca44f
@@ -666,34 +671,44 @@ finish:
edca44f
 	teardown_digests(ctx->cms);
edca44f
 }
edca44f
 
edca44f
+static inline void
edca44f
+handle_sign_helper(context *ctx, struct pollfd *pollfd, socklen_t size,
edca44f
+		   int attached, bool with_file_type)
edca44f
+{
edca44f
+	int rc = cms_context_alloc(&ctx->cms);
edca44f
+	if (rc < 0)
edca44f
+		return;
edca44f
+
edca44f
+	steal_from_cms(ctx->backup_cms, ctx->cms);
edca44f
+
edca44f
+	handle_signing(ctx, pollfd, size, attached, with_file_type);
edca44f
+
edca44f
+	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
edca44f
+	cms_context_fini(ctx->cms);
edca44f
+}
edca44f
+
edca44f
 static void
edca44f
 handle_sign_attached(context *ctx, struct pollfd *pollfd, socklen_t size)
edca44f
 {
edca44f
-	int rc = cms_context_alloc(&ctx->cms);
edca44f
-	if (rc < 0)
edca44f
-		return;
edca44f
+	handle_sign_helper(ctx, pollfd, size, 1, false);
edca44f
+}
edca44f
 
edca44f
-	steal_from_cms(ctx->backup_cms, ctx->cms);
edca44f
-
edca44f
-	handle_signing(ctx, pollfd, size, 1);
edca44f
-
edca44f
-	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
edca44f
-	cms_context_fini(ctx->cms);
edca44f
+static void
edca44f
+handle_sign_attached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size)
edca44f
+{
edca44f
+	handle_sign_helper(ctx, pollfd, size, 1, true);
edca44f
 }
edca44f
 
edca44f
 static void
edca44f
 handle_sign_detached(context *ctx, struct pollfd *pollfd, socklen_t size)
edca44f
 {
edca44f
-	int rc = cms_context_alloc(&ctx->cms);
edca44f
-	if (rc < 0)
edca44f
-		return;
edca44f
+	handle_sign_helper(ctx, pollfd, size, 0, false);
edca44f
+}
edca44f
 
edca44f
-	steal_from_cms(ctx->backup_cms, ctx->cms);
edca44f
-
edca44f
-	handle_signing(ctx, pollfd, size, 0);
edca44f
-
edca44f
-	hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms);
edca44f
-	cms_context_fini(ctx->cms);
edca44f
+static void
edca44f
+handle_sign_detached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size)
edca44f
+{
edca44f
+	handle_sign_helper(ctx, pollfd, size, 0, true);
edca44f
 }
edca44f
 
edca44f
 static void
edca44f
@@ -725,6 +740,12 @@ cmd_table_t cmd_table[] = {
edca44f
 		{ CMD_UNLOCK_TOKEN, handle_unlock_token, "unlock-token", 0 },
edca44f
 		{ CMD_SIGN_ATTACHED, handle_sign_attached, "sign-attached", 0 },
edca44f
 		{ CMD_SIGN_DETACHED, handle_sign_detached, "sign-detached", 0 },
edca44f
+		{ CMD_SIGN_ATTACHED_WITH_FILE_TYPE,
edca44f
+		  handle_sign_attached_with_file_type,
edca44f
+		  "sign-attached-with-file-type", 0 },
edca44f
+		{ CMD_SIGN_DETACHED_WITH_FILE_TYPE,
edca44f
+		  handle_sign_detached_with_file_type,
edca44f
+		  "sign-detached-with-file-type", 0 },
edca44f
 		{ CMD_RESPONSE, NULL, "response",  0 },
edca44f
 		{ CMD_IS_TOKEN_UNLOCKED, handle_is_token_unlocked,
edca44f
 			"is-token-unlocked", 0 },
edca44f
diff --git a/src/daemon.h b/src/daemon.h
edca44f
index dd430512f1a..834d62c72d0 100644
edca44f
--- a/src/daemon.h
edca44f
+++ b/src/daemon.h
edca44f
@@ -33,6 +33,8 @@ typedef enum {
edca44f
 	CMD_RESPONSE,
edca44f
 	CMD_IS_TOKEN_UNLOCKED,
edca44f
 	CMD_GET_CMD_VERSION,
edca44f
+	CMD_SIGN_ATTACHED_WITH_FILE_TYPE,
edca44f
+	CMD_SIGN_DETACHED_WITH_FILE_TYPE,
edca44f
 	CMD_LIST_END
edca44f
 } pesignd_cmd;
edca44f
 
edca44f
-- 
edca44f
2.26.2
edca44f