Re: [gssproxy] Re: cifs-utils, Linux cifs kernel client and gssproxy

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Simo,
Hello Steve,

> If something is needed in the short term, I thjink the quickest course
> of action is indeed to change the userspace helper to use gssapi
> function calls, so that they can be intercepted like we do for rpc.gssd
> (nfs client's userspace helper).

To get the ball rolling and give people (including myself and client) something to play with I went that route and extended cifs.upcall to fall back to GSS-API if no ticket cache nor keytab can be found for the user. An unpolished PoC patch is attached. (Sorry, for not putting it inline, have to rock the groupware at work. I will try to sort that once we've agreed this is the/a way to go.)

With that patch applied,  I can do a multiuser cifs mount using the system keytab and machine identity as usual and then have users access the mount using impersonated credentials from gssproxy. Quick demo:

[root@fedora33 ~]# umount /mnt
[root@fedora33 ~]# mount -o sec=krb5,multiuser,user=FEDORA33\$ //dc/share /mnt
[root@fedora33 ~]# ls -la /mnt
total 0
drwxr-xr-x.  2 root root   0 Jan  7 10:20 .
dr-xr-xr-x. 18 root root 238 Jan  6 13:59 ..
-rwxr-xr-x.  1 root root   0 Jan  5 17:02 bar
[root@fedora33 ~]# klist
klist: Credentials cache keyring 'persistent:0:krb_ccache_WZh7W8n' not found
[root@fedora33 ~]#

[adsuser@fedora33 ~]$ kdestroy
[adsuser@fedora33 ~]$ echo test > /mnt/test
[adsuser@fedora33 ~]$ cat /mnt/test
test
[adsuser@fedora33 ~]$ klist
klist: Credentials cache keyring 'persistent:1618201110:krb_ccache_SrGqT3F' not found
[adsuser@fedora33 ~]$

Server-side permissions are enforced:

[m@fedora33 ~]$ cat /mnt/test
test
[m@fedora33 ~]$ echo mytest > /mnt/test
-bash: /mnt/test: Permission denied
[m@fedora33 ~]$ klist
klist: Credentials cache keyring 'persistent:1000:1000' not found
[m@fedora33 ~]$

The gssproxy config for this configures a cifs-specific socket and enables impersonation for any user id:

[root@fedora33 ~]# cat /etc/gssproxy/99-cifs.conf
[service/cifs]
mechs = krb5
socket = /var/lib/gssproxy/cifs.sock
cred_store = keytab:/etc/krb5.keytab
cred_usage = initiate
euid = 0
impersonate = yes
allow_any_uid = yes

And request-key config for cifs.spnego enables use of gssproxy and the service-specific socket through environment variables:

[root@fedora33 ~]# cat /etc/request-key.d/cifs.spnego.conf
create  cifs.spnego    * *  /usr/bin/env GSS_USE_PROXY=yes GSSPROXY_SOCKET=/var/lib/gssproxy/cifs.sock /usr/sbin/cifs.upcall %k

(I see that nfs-utils' gssd does the same by setting the variables itself based on command line options. That could easily be done here as well.)
 
User FEDORA33$ (the computer object) needs to be enabled for delegation to service cifs. I've tested with a Fedora 33 client and Windows 2016 Active Directory server.

The patch is against current cifs-utils HEAD. It is lacking all the autoconf trimmings and intentionally forgoes reindents of existing code for clarity of what's being touched.

What do you think?

> Unfortunately I do not have the cycles to work on that myself at this
> time :-(

I have a client in very tangible need of this functionality who is a RedHat customer. Would it be helpful if they were to open a case with Redhat on this?

As an extension the above (but not to distract from the focus of getting something to work at all first):

I rather accidentally also played around with delegating retrieval of the mount credentials into gssproxy as well (due to not realising that username=FEDORA33$ would just activate the keytab codepath in cifs.upcall).

This can be done by leaving out the username from the mount command, marking euid 0 as trusted for access to the keytab in gssproxy and adding a fallback principal to the gssproxy config (because cifs.upcall in this case does not submit a desired name for the credential):

[root@fedora33 ~]# mount -o sec=krb5,multiuser //dc/share /mnt
[root@fedora33 ~]# cat /etc/gssproxy/99-cifs.conf
[service/cifs]
mechs = krb5
socket = /var/lib/gssproxy/cifs.sock
cred_store = keytab:/etc/krb5.keytab
cred_usage = initiate
euid = 0
trusted = yes
impersonate = yes
krb5_principal = cifs-mount
allow_any_uid = yes

While this works, it requires a separate user who would then carefully need to be kept out of any sensitive file access groups.

When trying to use the machine identity FEDORA33$ instead, I ran into a peculiar error from the AD KDC:

[root@fedora33 ~]# cat /etc/gssproxy/99-cifs.conf
[service/cifs]
mechs = krb5
socket = /var/lib/gssproxy/cifs.sock
cred_store = keytab:/etc/krb5.keytab
cred_usage = initiate
euid = 0
trusted = yes
impersonate = yes
krb5_principal = FEDORA33$
allow_any_uid = yes
[root@fedora33 ~]# gssproxy -i -d &
[2] 3814
[root@fedora33 ~]# [2021/01/07 10:01:10]: Debug Enabled (level: 1)
[2021/01/07 10:01:10]: Service: nfs-server, Keytab: /etc/krb5.keytab, Enctype: 17
[2021/01/07 10:01:10]: Service: cifs, Keytab: /etc/krb5.keytab, Enctype: 17
[2021/01/07 10:01:10]: Service: nfs-client, Keytab: /etc/krb5.keytab, Enctype: 17
[2021/01/07 10:01:10]: Client [2021/01/07 10:01:10]: (/usr/sbin/gssproxy) [2021/01/07 10:01:10]:  connected (fd = 11)[2021/01/07 10:01:10]:  (pid = 3814) (uid = 0) (gid = 0)[2021/01/07 10:01:10]:  (context = system_u:system_r:kernel_t:s0)[2021/01/07 10:01:10]:

[root@fedora33 ~]# mount -o sec=krb5,multiuser //dc/share /mnt
[2021/01/07 10:01:13]: Client [2021/01/07 10:01:13]: (/usr/sbin/cifs.upcall) [2021/01/07 10:01:13]:  connected (fd = 12)[2021/01/07 10:01:13]:  (pid = 3824) (uid = 0) (gid = 0)[2021/01/07 10:01:13]:  (context = system_u:system_r:kernel_t:s0)[2021/01/07 10:01:13]:
[CID 12][2021/01/07 10:01:13]: gp_rpc_execute: executing 6 (GSSX_ACQUIRE_CRED) for service "cifs", euid: 0,socket: /var/lib/gssproxy/cifs.sock
gssproxy[3814]: (OID: { 1 2 840 113554 1 2 2 }) Unspecified GSS failure.  Minor code may provide more information, KDC has no support for padata type
[CID 12][2021/01/07 10:01:13]: gp_rpc_execute: executing 8 (GSSX_INIT_SEC_CONTEXT) for service "cifs", euid: 0,socket: /var/lib/gssproxy/cifs.sock
gssproxy[3814]: (OID: { 1 2 840 113554 1 2 2 }) Unspecified GSS failure.  Minor code may provide more information, KDC has no support for padata type
[CID 12][2021/01/07 10:01:13]: gp_rpc_execute: executing 6 (GSSX_ACQUIRE_CRED) for service "cifs", euid: 0,socket: /var/lib/gssproxy/cifs.sock
gssproxy[3814]: (OID: { 1 2 840 113554 1 2 2 }) Unspecified GSS failure.  Minor code may provide more information, KDC has no support for padata type
[CID 12][2021/01/07 10:01:13]: gp_rpc_execute: executing 8 (GSSX_INIT_SEC_CONTEXT) for service "cifs", euid: 0,socket: /var/lib/gssproxy/cifs.sock
gssproxy[3814]: (OID: { 1 2 840 113554 1 2 2 }) Unspecified GSS failure.  Minor code may provide more information, KDC has no support for padata type
mount error(126): Required key not available
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg)

With more debugging it appears that gssproxy tries to impersonate user FEDORA33$ with a credential which is also for FEDORA33$. After further testing it seems this is generally not allowed or just not working due to never being tested because it is unnecessary: If we can acquire a impersonation credential for that identity we should also be able to get the actual access credential as well.

>From looking at the nfs-utils gssd code it appears the only reason it hasn't run into this case yet is because it handles the machine credentials itself using krb5 functions.

The second attached patch against current gssproxy HEAD adds that distinction and makes this case work as an optional extension with fallback into the default codepath on error.

Does that make sense?
Is it sane, security wise, do you think?
-- 
Thanks,
Michael
________________________________________
From: Simo Sorce <simo@xxxxxxxxxx>
Sent: 16 December 2020 15:31:40
To: The GSS-Proxy developers and users mailing list; linux-cifs@xxxxxxxxxxxxxxx
Cc: samba-technical@xxxxxxxxxxxxxxx
Subject: [gssproxy] Re: cifs-utils, Linux cifs kernel client and gssproxy

Caution! External email. Do not open attachments or click links, unless this email comes from a known sender and you know the content is safe.

Hi Michael,
as you say the best course of action would be for cifs.ko to move to
use the RPC interface we defined for knfsd (with any extensions that
may  be needed), and we had discussions in the past with cifs upstream
developers about it. But nothing really materialized.

If something is needed in the short term, I thjink the quickest course
of action is indeed to change the userspace helper to use gssapi
function calls, so that they can be intercepted like we do for rpc.gssd
(nfs client's userspace helper).

Unfortunately I do not have the cycles to work on that myself at this
time :-(

HTH,
Simo.

On Wed, 2020-12-16 at 10:01 +0000, Weiser, Michael wrote:
> Hello,
>
> I have a use-case for authentication of Linux cifs client mounts without the user being present (e.g. from batch jobs) using gssproxy's impersonation feature with Kerberos Constrained Delegation similar to how it can be done for NFS[1].
>
> My understanding is that currently neither the Linux cifs kernel client nor cifs-utils userland tools support acquiring credentials using gssproxy. The former uses a custom upcall interface to talk to cifs.spnego from cifs-utils. The latter then goes looking for Kerberos ticket caches using libkrb5 functions, not GSSAPI, which prevents gssproxy from interacting with it.[2]
>
> From what I understand, the preferred method would be to switch the Linux kernel client upcall to the RPC protocol defined by gssproxy[3] (as has been done for the Linux kernel NFS server already replacing rpc.svcgssd[4]). The kernel could then, at least optionally, talk to gssproxy directly to try and obtain credentials.
>
> Failing that, cifs-utils' cifs.spnego could be switched to GSSAPI so that gssproxy's interposer plugin could intercept GSSAPI calls and provide them with the required credentials (similar to the NFS client rpc.gssd[5]).
>
> Assuming my understanding is correct so far:
>
> Is anyone doing any work on this and could use some help (testing, coding)?
> What would be expected complexity and possible roadblocks when trying to make a start at implementing this?
> Or is the idea moot due to some constraint or recent development I'm not aware of?
>
> I have found a recent discussion of the topic on linux-cifs[6] which provided no definite answer though.
>
> As a crude attempt at an explicit userspace workaround I tried but failed to trick smbclient into initialising a ticket cache using gssproxy for cifs.spnego to find later on.
> Is this something that could be implemented without too much redundant effort (or should already work, perhaps using a different tool)?
>
> [1] https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#user-impersonation-via-constrained-delegation
> [2] https://pagure.io/gssproxy/issue/56
> [3] https://github.com/gssapi/gssproxy/blob/main/docs/ProtocolDocumentation.md
> [4] https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#nfs-server
> [5] https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#nfs-client
> [6] https://www.spinics.net/lists/linux-cifs/msg20182.html
> --
> Thanks,
> Michael
> _______________________________________________
> gss-proxy mailing list -- gss-proxy@xxxxxxxxxxxxxxxxxxxxxx
> To unsubscribe send an email to gss-proxy-leave@xxxxxxxxxxxxxxxxxxxxxx
> Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
> List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
> List Archives: https://lists.fedorahosted.org/archives/list/gss-proxy@xxxxxxxxxxxxxxxxxxxxxx

--
Simo Sorce
RHEL Crypto Team
Red Hat, Inc



_______________________________________________
gss-proxy mailing list -- gss-proxy@xxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to gss-proxy-leave@xxxxxxxxxxxxxxxxxxxxxx
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedorahosted.org/archives/list/gss-proxy@xxxxxxxxxxxxxxxxxxxxxx
From 61e9ed9b811573ad02f4085979925a3d2b164762 Mon Sep 17 00:00:00 2001
From: Michael Weiser <michael.weiser@xxxxxxxx>
Date: Tue, 5 Jan 2021 17:08:30 +0100
Subject: [PATCH] GSS-API PoC

PoC to test out gssproxy usage through GSS-API. If no useable ticket cache or
keytab can be found, fall on through into credential handling anyway but then
divert into GSS routines. If no gssproxy is available this will still error out
silently because no ticket cache is available. With gssproxy enabled,
credentials can be retrieved from there and allow unattended access to shares
e.g. from batch jobs.

Signed-off-by: Michael Weiser <michael.weiser@xxxxxxxx>
---
 Makefile.am   |   2 +-
 cifs.upcall.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 141 insertions(+), 10 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 84dd119..38babb3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,7 @@ sbin_PROGRAMS =
 if CONFIG_CIFSUPCALL
 sbin_PROGRAMS += cifs.upcall
 cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c
-cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD) $(CAPNG_LDADD)
+cifs_upcall_LDADD = -ltalloc -lkeyutils -lgssapi_krb5 $(KRB5_LDADD) $(CAPNG_LDADD)
 rst_man_pages += cifs.upcall.8
 #
 # Fix the pathnames in manpages. To prevent @label@ being replaced by m4, we
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 400b42d..1a4b1a6 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -36,6 +36,11 @@
 #elif defined(HAVE_KRB5_H)
 #include <krb5.h>
 #endif
+
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+#include <sys/utsname.h>
+
 #include <syslog.h>
 #include <dirent.h>
 #include <sys/types.h>
@@ -457,6 +462,8 @@ icfk_cleanup:
 	goto out;
 }
 
+#define CIFS_SERVICE_NAME "cifs"
+
 static int
 cifs_krb5_get_req(const char *host, krb5_ccache ccache,
 		  DATA_BLOB * mechtoken, DATA_BLOB * sess_key)
@@ -478,8 +485,8 @@ cifs_krb5_get_req(const char *host, krb5_ccache ccache,
 		return ret;
 	}
 
-	ret = krb5_sname_to_principal(context, host, "cifs", KRB5_NT_UNKNOWN,
-					&in_creds.server);
+	ret = krb5_sname_to_principal(context, host, CIFS_SERVICE_NAME,
+					KRB5_NT_UNKNOWN, &in_creds.server);
 	if (ret) {
 		syslog(LOG_DEBUG, "%s: unable to convert sname to princ (%s).",
 		       __func__, host);
@@ -578,6 +585,120 @@ out_free_principal:
 	return ret;
 }
 
+static void cifs_gss_display_status_1(char *m, OM_uint32 code, int type) {
+	OM_uint32 min_stat;
+	gss_buffer_desc msg;
+	OM_uint32 msg_ctx;
+
+	msg_ctx = 0;
+	while (1) {
+		(void) gss_display_status(&min_stat, code, type,
+				GSS_C_NULL_OID, &msg_ctx, &msg);
+		syslog(LOG_DEBUG, "GSS-API error %s: %s\n", m, (char *) msg.value);
+		(void) gss_release_buffer(&min_stat, &msg);
+
+		if (!msg_ctx)
+			break;
+	}
+}
+
+void cifs_gss_display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) {
+	cifs_gss_display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+	cifs_gss_display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+static int
+cifs_gss_get_req(const char *host, DATA_BLOB * mechtoken, DATA_BLOB * sess_key)
+{
+	OM_uint32 maj_stat, min_stat;
+	gss_name_t target_name;
+	gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+	gss_buffer_desc output_token;
+	gss_krb5_lucid_context_v1_t *lucid_ctx = NULL;
+	gss_krb5_lucid_key_t *key = NULL;
+
+	size_t service_name_len = sizeof(CIFS_SERVICE_NAME) + 1 /* @ */ +
+		strlen(host) + 1;
+	char *service_name = malloc(service_name_len);
+	if (!service_name) {
+		syslog(LOG_DEBUG, "out of memory allocating service name");
+		goto out;
+	}
+
+	snprintf(service_name, service_name_len,
+			"%s@%s", CIFS_SERVICE_NAME, host);
+	gss_buffer_desc target_name_buf;
+	target_name_buf.value = service_name;
+	target_name_buf.length = service_name_len;
+
+	maj_stat = gss_import_name(&min_stat, &target_name_buf,
+			(gss_OID)gss_nt_service_name, &target_name);
+	free(service_name);
+	if (GSS_ERROR(maj_stat)) {
+		cifs_gss_display_status("gss_import_name", maj_stat, min_stat);
+		goto out;
+	}
+
+	maj_stat = gss_init_sec_context(&min_stat,
+			GSS_C_NO_CREDENTIAL,	/* claimant_cred_handle */
+			&ctx,
+			target_name,
+			gss_mech_krb5,	/* force krb5 */
+			0,	/* flags */
+			0,	/* time_req */
+			GSS_C_NO_CHANNEL_BINDINGS,	/* input_chan_bindings */
+			GSS_C_NO_BUFFER,
+			NULL,	/* actual mech type */
+			&output_token,
+			NULL,	/* ret_flags */
+			NULL);	/* time_rec */
+	if (maj_stat != GSS_S_COMPLETE &&
+		maj_stat != GSS_S_CONTINUE_NEEDED) {
+		cifs_gss_display_status("init_sec_context", maj_stat, min_stat);
+		goto out_release_target_name;
+	}
+
+	/* as luck would have it, GSS-API hands us the finished article */
+	*mechtoken = data_blob(output_token.value, output_token.length);
+
+	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &ctx, 1,
+			(void **)&lucid_ctx);
+	if (GSS_ERROR(maj_stat)) {
+		cifs_gss_display_status("gss_krb5_export_lucid_sec_context",
+				maj_stat, min_stat);
+		goto out_free_sec_ctx;
+	}
+
+	switch (lucid_ctx->protocol) {
+	case 0:
+		key = &lucid_ctx->rfc1964_kd.ctx_key;
+		break;
+
+	case 1:
+		if (lucid_ctx->cfx_kd.have_acceptor_subkey) {
+			key = &lucid_ctx->cfx_kd.acceptor_subkey;
+		} else {
+			key = &lucid_ctx->cfx_kd.ctx_key;
+		}
+		break;
+	default:
+		syslog(LOG_DEBUG, "wrong lucid context protocol %d", lucid_ctx->protocol);
+		goto out_free_lucid_ctx;
+	}
+
+	*sess_key = data_blob(key->data, key->length);
+
+out_free_lucid_ctx:
+	(void) gss_krb5_free_lucid_sec_context(&min_stat, lucid_ctx);
+out_free_sec_ctx:
+	(void) gss_delete_sec_context(&min_stat, &ctx, GSS_C_NO_BUFFER);
+	(void) gss_release_buffer(&min_stat, &output_token);
+out_release_target_name:
+	(void) gss_release_name(&min_stat, &target_name);
+out:
+	return GSS_ERROR(maj_stat);
+}
+
 /*
  * Prepares AP-REQ data for mechToken and gets session key
  * Uses credentials from cache. It will not ask for password
@@ -603,10 +724,24 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
 		 DATA_BLOB * sess_key, krb5_ccache ccache)
 {
 	int retval;
-	DATA_BLOB tkt, tkt_wrapped;
+	DATA_BLOB tkt_wrapped;
 
 	syslog(LOG_DEBUG, "%s: getting service ticket for %s", __func__, host);
 
+	/* fall back to gssapi if there's no credential cache or no TGT
+	 * so that gssproxy can maybe help out */
+	if (!ccache) {
+		syslog(LOG_DEBUG, "%s: using GSS-API", __func__);
+		retval = cifs_gss_get_req(host, &tkt_wrapped, sess_key);
+		if (retval) {
+			syslog(LOG_DEBUG, "%s: failed to obtain service ticket via GSS (%d)",
+			__func__, retval);
+			return retval;
+		}
+	} else {
+		DATA_BLOB tkt;
+		syslog(LOG_DEBUG, "%s: using native krb5", __func__);
+
 	/* get a kerberos ticket for the service and extract the session key */
 	retval = cifs_krb5_get_req(host, ccache, &tkt, sess_key);
 	if (retval) {
@@ -619,12 +754,13 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
 
 	/* wrap that up in a nice GSS-API wrapping */
 	tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
+		data_blob_free(&tkt);
+	}
 
 	/* and wrap that in a shiny SPNEGO wrapper */
 	*secblob = gen_negTokenInit(oid, tkt_wrapped);
 
 	data_blob_free(&tkt_wrapped);
-	data_blob_free(&tkt);
 	return retval;
 }
 
@@ -1132,11 +1268,6 @@ int main(const int argc, char *const argv[])
 	if (ccache == NULL && arg.username != NULL)
 		ccache = init_cc_from_keytab(keytab_name, arg.username);
 
-	if (ccache == NULL) {
-		rc = 1;
-		goto out;
-	}
-
 	host = arg.hostname;
 
 	// do mech specific authorization
-- 
2.29.2

From 2db433a9998dceca7f2dfac8b0b1c8f097aed488 Mon Sep 17 00:00:00 2001
From: Michael Weiser <michael.weiser@xxxxxxxx>
Date: Thu, 7 Jan 2021 10:34:15 +0100
Subject: [PATCH] Handle impersonation of oneself

When trying to impersonate the user which has been selected as impersonation
credential, an AD KDC returns error:

GSSX_RES_ACQUIRE_CRED( status: { 851968 { 1 2 840 113554 1 2 2 } 2529638928
"Unspecified GSS failure.  Minor code may provide more information" "KDC has no
support for padata type" [  ] } output_cred_handle: <Null> )

Apparently, to impersonate oneself is not allowed. Also, it is likely not even
necessary: If we can get impersonation credentials from credstores, we can at
least try to short circuit and get actual user credentials the same way.

With this patch it becomes possible to delegate the acquisition of e.g. cifs
mount credentials from cifs.upcall into gssproxy and use the host identity
(e.g. HOSTNAME$@REALM of AD) while it is also being selected as impersonation
credential due to the order of keys in the keytab.

Signed-off-by: Michael Weiser <michael.weiser@xxxxxxxx>
---
 src/gp_creds.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/gp_creds.c b/src/gp_creds.c
index 424cf35..14ab364 100644
--- a/src/gp_creds.c
+++ b/src/gp_creds.c
@@ -667,6 +667,41 @@ uint32_t gp_add_krb5_creds(uint32_t *min,
             if (ret_maj) {
                 goto done;
             }
+
+            if (req_name != GSS_C_NO_NAME) {
+                int equal = 0;
+
+                ret_maj = gss_inquire_cred(&ret_min, impersonator_cred,
+                                           &target_name, NULL, NULL, NULL);
+                if (ret_maj) {
+                    goto done;
+                }
+
+                ret_maj = gss_compare_name(&ret_min, target_name,
+                                           req_name, &equal);
+                if (ret_maj) {
+                    goto done;
+                }
+
+                /* if impersonator credential retrieval yielded the requested client
+                 * name, we do not need to impersonate. Also, in AD an attempt to
+                 * impersonate oneself yields an error "KDC has no support for padata
+                 * type" */
+                if (equal) {
+                     ret_maj = gss_acquire_cred_from(&ret_min, req_name, GSS_C_INDEFINITE,
+                                                     &desired_mechs, cred_usage,
+                                                     &cred_store, &user_cred,
+                                                     actual_mechs, NULL);
+                     if (!ret_maj) {
+                         *output_cred_handle = user_cred;
+                         user_cred = GSS_C_NO_CREDENTIAL;
+                         goto done;
+                     }
+
+                     /* fall on through, if failed */
+                 }
+            }
+
             input_cred = impersonator_cred;
             break;
         case ACQ_IMPNAME:
-- 
2.29.2


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux