[pve-devel] [PATCH v3 cluster 1/2] pmxcfs: add verify_token IPCC request

Fabian Grünbichler f.gruenbichler at proxmox.com
Tue Jan 21 13:53:57 CET 2020


Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---

Notes:
    v2->v3:
    - fix out-of-bounds write
    - drop null-termination, instead only compare lines that have the proper length
    - don't include terminating \0 in tokenlen

 data/src/cfs-ipc-ops.h |  2 ++
 data/src/server.c      | 55 ++++++++++++++++++++++++++++++++++++++++++
 data/src/status.c      |  1 +
 data/PVE/Cluster.pm    | 18 ++++++++++++++
 4 files changed, 76 insertions(+)

diff --git a/data/src/cfs-ipc-ops.h b/data/src/cfs-ipc-ops.h
index e4026ad..9d788bc 100644
--- a/data/src/cfs-ipc-ops.h
+++ b/data/src/cfs-ipc-ops.h
@@ -41,4 +41,6 @@
 
 #define CFS_IPC_GET_GUEST_CONFIG_PROPERTY 11
 
+#define CFS_IPC_VERIFY_TOKEN 12
+
 #endif
diff --git a/data/src/server.c b/data/src/server.c
index 36acc1d..8519001 100644
--- a/data/src/server.c
+++ b/data/src/server.c
@@ -89,6 +89,11 @@ typedef struct {
 	char property[];
 } cfs_guest_config_propery_get_request_header_t;
 
+typedef struct {
+	struct qb_ipc_request_header req_header;
+	char token[];
+} cfs_verify_token_request_header_t;
+
 struct s1_context {
 	int32_t client_pid;
 	uid_t uid;
@@ -343,6 +348,56 @@ static int32_t s1_msg_process_fn(
 
 			result = cfs_create_guest_conf_property_msg(outbuf, memdb, rh->property, rh->vmid);
 		}
+	} else if (request_id == CFS_IPC_VERIFY_TOKEN) {
+
+		cfs_verify_token_request_header_t *rh = (cfs_verify_token_request_header_t *) data;
+		int tokenlen = request_size - G_STRUCT_OFFSET(cfs_verify_token_request_header_t, token) - 1;
+
+		if (tokenlen <= 0) {
+			cfs_debug("tokenlen <= 0, %d", tokenlen);
+			result = -EINVAL;
+		} else if (memchr(rh->token, '\n', tokenlen) != NULL) {
+			cfs_debug("token contains newline");
+			result = -EINVAL;
+		} else if (rh->token[tokenlen] != '\0') {
+			cfs_debug("token not NULL-terminated");
+			result = -EINVAL;
+		} else if (strnlen(rh->token, tokenlen) != tokenlen) {
+			cfs_debug("token contains NULL-byte");
+			result = -EINVAL;
+		} else {
+			cfs_debug("cfs_verify_token: basic validity checked, reading token.cfg");
+			gpointer tmp = NULL;
+			int bytes_read = memdb_read(memdb, "priv/token.cfg", &tmp);
+			size_t remaining = bytes_read > 0 ? bytes_read : 0;
+			if (tmp != NULL && remaining >= tokenlen) {
+				char *line = (char *) tmp;
+				char *next_line;
+				const char *const end = line + remaining;
+				size_t linelen;
+
+				while (line != NULL) {
+					next_line = memchr(line, '\n', remaining);
+					linelen = next_line == NULL ? remaining : next_line - line;
+					if (linelen == tokenlen && strncmp(line, rh->token, linelen) == 0) {
+						result = 0;
+						break;
+					}
+					line = next_line;
+					if (line != NULL) {
+						line += 1;
+						remaining = end - line;
+					}
+				}
+				if (line == NULL) {
+					result = -ENOENT;
+				}
+				g_free(tmp);
+			} else {
+				cfs_debug("token: token.cfg does not exist - ENOENT");
+				result = -ENOENT;
+			}
+		}
 	}
 
 	cfs_debug("process result %d", result);
diff --git a/data/src/status.c b/data/src/status.c
index d6dccc1..2dde874 100644
--- a/data/src/status.c
+++ b/data/src/status.c
@@ -100,6 +100,7 @@ static memdb_change_t memdb_change_array[] = {
 	{ .path = "sdn/zones.cfg.new" },
 	{ .path = "sdn/controllers.cfg" },
 	{ .path = "sdn/controllers.cfg.new" },
+	{ .path = "priv/token.cfg" },
 };
 
 static GMutex mutex;
diff --git a/data/PVE/Cluster.pm b/data/PVE/Cluster.pm
index b4fac03..b329b23 100644
--- a/data/PVE/Cluster.pm
+++ b/data/PVE/Cluster.pm
@@ -187,6 +187,18 @@ my $ipcc_get_cluster_log = sub {
     return &$ipcc_send_rec(CFS_IPC_GET_CLUSTER_LOG, $bindata);
 };
 
+my $ipcc_verify_token = sub {
+    my ($full_token) = @_;
+
+    my $bindata = pack "Z*", $full_token;
+    my $res = PVE::IPCC::ipcc_send_rec(CFS_IPC_VERIFY_TOKEN, $bindata);
+
+    return 1 if $! == 0;
+    return 0 if $! == ENOENT;
+
+    die "$!\n";
+};
+
 my $ccache = {};
 
 sub cfs_update {
@@ -447,6 +459,12 @@ sub get_cluster_log {
     return &$ipcc_get_cluster_log($user, $max);
 }
 
+sub verify_token {
+    my ($userid, $token) = @_;
+
+    return &$ipcc_verify_token("$userid $token");
+}
+
 my $file_info = {};
 
 sub cfs_register_file {
-- 
2.20.1




More information about the pve-devel mailing list