diff mbox series

[cifs-utils,RFC,04/12] upcall-helper: obtain and parse key description, assigning fields to key_vars

Message ID 20250510161609.2615639-5-sorenson@redhat.com
State New
Headers show
Series cifs.upcall helper script enabling complex key description matching | expand

Commit Message

Frank Sorenson May 10, 2025, 4:16 p.m. UTC
Execute keyctl to get the key's description, and parse the
description fields, assigning to key_vars for use during matching.

Still just executing the upcall with keyid.

Signed-off-by: Frank Sorenson <sorenson@redhat.com>
---
 contrib/upcall-helper/cifs-upcall-helper | 49 ++++++++++++++++++++++++
 1 file changed, 49 insertions(+)
diff mbox series

Patch

diff --git a/contrib/upcall-helper/cifs-upcall-helper b/contrib/upcall-helper/cifs-upcall-helper
index eead9c7..ee62aff 100755
--- a/contrib/upcall-helper/cifs-upcall-helper
+++ b/contrib/upcall-helper/cifs-upcall-helper
@@ -23,6 +23,7 @@ 
 
 use strict;
 use warnings;
+use POSIX;
 use Sys::Syslog;
 
 my $log_ident = 'cifs-upcall-helper';
@@ -33,6 +34,15 @@  my $log_level = 0;
 # 2 - verbose debugging (LOG_INFO)
 
 my $keyid;
+my %key_vars;
+
+# keyctl rdescribe output format:
+#  cifs.spnego;0;0;39010000;ver=0x2;host=vm1;ip4=192.168.122.73;sec=krb5;uid=0x0;creduid=0x0;user=user1;pid=0xbaf7d;upcall_target=mount
+#
+#  user=<username> is optional
+#  upcall_target=(mount|app) is optional
+my $key_descriptionv2_re = qr/^cifs.spnego;([0-9]+);([0-9]+);([0-9a-f]+);ver=0x2;host=([^;]+);(ip4|ip6)=([^;]+);sec=(krb5|mskrb5|iakerb);uid=(0x[0-9a-f]+);creduid=(0x[0-9a-f]+)(?:;user=([^;]+))?;pid=(0x[0-9a-f]+)(?:;upcall_target=(mount|app))?$/;
+my @descriptionv2_keys = ('keyuid', 'keygid', 'perms', 'host', 'ipv', 'ip', 'sec', 'uid', 'creduid', 'user', 'pid', 'upcall_target');
 
 sub log_msg {
 	my $msg_level = shift;
@@ -58,6 +68,43 @@  sub exec_upcall {
 	log_msg 1, sprintf("executing cifs.upcall: %s", join(' ', @upcall_args));
 	exec { $upcall_args[0] } @upcall_args;
 }
+sub get_key_description {
+	my $keyid = shift;
+
+	if (! open KEYCTL, "/usr/bin/keyctl rdescribe $keyid 2>&1 |") {
+		log_msg 0, "Error executing keyctl: $!";
+		exec_upcall;
+	}
+	my $rdescribe = <KEYCTL>;
+	chomp $rdescribe;
+	close KEYCTL;
+	if ($?) {
+		log_msg 0, "Error executing keyctl: $rdescribe";
+		exec_upcall;
+	}
+
+	log_msg 2, "description for key $keyid: $rdescribe";
+	return $rdescribe;
+}
+sub parse_key_description {
+	my $key_description_str = shift;
+	if ($key_description_str !~ $key_descriptionv2_re) {
+		log_msg 0, "could not match key description to known format: $key_description_str";
+		log_msg 1, "executing upcall with default parameters";
+		exec_upcall;
+	}
+	@key_vars{@descriptionv2_keys} = $key_description_str =~ $key_descriptionv2_re;
+
+	$key_vars{'uid'} = scalar POSIX::strtol($key_vars{'uid'}, 16);
+	$key_vars{'creduid'} = scalar POSIX::strtol($key_vars{'creduid'}, 16);
+	$key_vars{'user'} = '' if !defined $key_vars{'user'};
+	$key_vars{'upcall_target'} = '' if !defined $key_vars{'upcall_target'};
+	log_msg 1, sprintf("description for key %d  keyuid: %d, keygid: %d, perms: %d, host %s, ipv: %s, ip: %s, sec: %s, uid: %d, creduid: %d, user %s, upcall_target: %s",
+		$keyid, $key_vars{'keyuid'}, $key_vars{'keygid'}, $key_vars{'perms'},
+		$key_vars{'host'}, $key_vars{'ipv'}, $key_vars{'ip'},
+		$key_vars{'sec'}, $key_vars{'uid'}, $key_vars{'creduid'},
+		$key_vars{'user'}, $key_vars{'upcall_target'});
+}
 
 if ($#ARGV ne 0) {
 	if (-t STDOUT) {
@@ -71,4 +118,6 @@  $keyid = $ARGV[0];
 
 log_msg 1, "$log_ident - keyid: $keyid";
 
+my $key_description_str = get_key_description $keyid;
+parse_key_description $key_description_str;
 exec_upcall;