Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: Samuel Cabrero <scabrero@suse.com>
To: linux-cifs@vger.kernel.org
Cc: smfrench@gmail.com, pc@manguebit.com, ronniesahlberg@gmail.com,
	sprasad@microsoft.com, tom@talpey.com, bharathsm@microsoft.com,
	henrique.carvalho@suse.com, ematsumiya@suse.de,
	Samuel Cabrero <scabrero@suse.com>
Subject: [PATCH 14/18] smb:client: Cache auth info
Date: Fri, 10 Jul 2026 11:16:33 +0200	[thread overview]
Message-ID: <20260710091637.58873-15-scabrero@suse.com> (raw)
In-Reply-To: <20260710091637.58873-1-scabrero@suse.com>

Continue reducing dependency from tcon. Now the registration have all
required information to operate on its own and register/unregister as
necessary.

Signed-off-by: Samuel Cabrero <scabrero@suse.com>
---
 fs/smb/client/cifs_swn.c | 153 +++++++++++++++++++++++++++++++++++----
 1 file changed, 138 insertions(+), 15 deletions(-)

diff --git a/fs/smb/client/cifs_swn.c b/fs/smb/client/cifs_swn.c
index 7e665b657f8d..6d8e3b94a432 100644
--- a/fs/smb/client/cifs_swn.c
+++ b/fs/smb/client/cifs_swn.c
@@ -30,6 +30,18 @@ struct cifs_swn_reg {
 	bool share_name_notify;
 	bool ip_notify;
 
+	/* Need to keep this information to re-register when reconnecting */
+	enum securityEnum auth_type;
+	union {
+		struct {
+		} kerberos;
+		struct {
+			const char *domain_name;
+			const char *user_name;
+			const char *password;
+		} ntlm;
+	} authinfo;
+
 	struct cifs_tcon *tcon;
 
 	unsigned long check_interval;
@@ -54,7 +66,92 @@ struct cifs_swn_notification {
 	struct cifs_swn_reg *swnreg;
 };
 
-static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
+static int cifs_swn_reg_set_auth(struct cifs_swn_reg *swnreg,
+				 const struct cifs_tcon *tcon)
+{
+	swnreg->auth_type =
+		cifs_select_sectype(tcon->ses->server, tcon->ses->sectype);
+	switch (swnreg->auth_type) {
+	case Kerberos:
+		break;
+	case NTLMv2:
+	case RawNTLMSSP:
+		if (tcon->ses->user_name != NULL) {
+			swnreg->authinfo.ntlm.user_name =
+				kstrdup(tcon->ses->user_name, GFP_KERNEL);
+			if (swnreg->authinfo.ntlm.user_name == NULL)
+				return -ENOMEM;
+		}
+		if (tcon->ses->domainName != NULL) {
+			swnreg->authinfo.ntlm.domain_name =
+				kstrdup(tcon->ses->domainName, GFP_KERNEL);
+			if (swnreg->authinfo.ntlm.domain_name == NULL) {
+				kfree(swnreg->authinfo.ntlm.user_name);
+				return -ENOMEM;
+			}
+		}
+		if (tcon->ses->password != NULL) {
+			swnreg->authinfo.ntlm.password =
+				kstrdup(tcon->ses->password, GFP_KERNEL);
+			if (swnreg->authinfo.ntlm.password == NULL) {
+				kfree(swnreg->authinfo.ntlm.user_name);
+				kfree(swnreg->authinfo.ntlm.domain_name);
+				return -ENOMEM;
+			}
+		}
+		break;
+	default:
+		cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__,
+			 swnreg->auth_type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static bool cifs_swn_str_equal(const char *a, const char *b)
+{
+	if (a == b)
+		return true;
+
+	if (a == NULL || b == NULL)
+		return false;
+
+	return strcmp(a, b) == 0;
+}
+
+static bool cifs_swn_auth_info_equal(const struct cifs_swn_reg *swnreg,
+				     const struct cifs_tcon *tcon)
+{
+	enum securityEnum auth_type =
+		cifs_select_sectype(tcon->ses->server, tcon->ses->sectype);
+	if (swnreg->auth_type != auth_type)
+		return false;
+
+	switch (auth_type) {
+	case Kerberos:
+		break;
+	case NTLMv2:
+	case RawNTLMSSP:
+		if (!cifs_swn_str_equal(tcon->ses->user_name,
+					swnreg->authinfo.ntlm.user_name))
+			return false;
+		if (!cifs_swn_str_equal(tcon->ses->domainName,
+					swnreg->authinfo.ntlm.domain_name))
+			return false;
+		if (!cifs_swn_str_equal(tcon->ses->password,
+					swnreg->authinfo.ntlm.password))
+			return false;
+		break;
+	default:
+		cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__,
+			 auth_type);
+		return false;
+	}
+
+	return true;
+}
+
+static int cifs_swn_auth_info_krb(struct sk_buff *skb)
 {
 	int ret;
 
@@ -65,24 +162,28 @@ static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
 	return 0;
 }
 
-static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb)
+static int cifs_swn_auth_info_ntlm(struct cifs_swn_reg *swnreg,
+				   struct sk_buff *skb)
 {
 	int ret;
 
-	if (tcon->ses->user_name != NULL) {
-		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name);
+	if (swnreg->authinfo.ntlm.user_name != NULL) {
+		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME,
+				     swnreg->authinfo.ntlm.user_name);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (tcon->ses->password != NULL) {
-		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password);
+	if (swnreg->authinfo.ntlm.password != NULL) {
+		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD,
+				     swnreg->authinfo.ntlm.password);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (tcon->ses->domainName != NULL) {
-		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName);
+	if (swnreg->authinfo.ntlm.domain_name != NULL) {
+		ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME,
+				     swnreg->authinfo.ntlm.domain_name);
 		if (ret < 0)
 			return ret;
 	}
@@ -160,6 +261,10 @@ static bool cifs_swn_reg_tcon_matches(const struct cifs_swn_reg *swnreg,
 	else
 		tcon_dstaddr = &tcon->ses->server->dstaddr;
 
+	/* Auth info must match */
+	if (!cifs_swn_auth_info_equal(swnreg, tcon))
+		return false;
+
 	/* Address must always match */
 	if (!cifs_match_ipaddr((struct sockaddr *)&swnreg->addr,
 			       (struct sockaddr *)tcon_dstaddr))
@@ -193,7 +298,6 @@ static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg,
 {
 	struct sk_buff *skb;
 	struct genlmsghdr *hdr;
-	enum securityEnum authtype;
 	int ret;
 
 	skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -241,10 +345,9 @@ static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg,
 			goto nlmsg_fail;
 	}
 
-	authtype = cifs_select_sectype(tcon->ses->server, tcon->ses->sectype);
-	switch (authtype) {
+	switch (swnreg->auth_type) {
 	case Kerberos:
-		ret = cifs_swn_auth_info_krb(tcon, skb);
+		ret = cifs_swn_auth_info_krb(skb);
 		if (ret < 0) {
 			cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret);
 			goto nlmsg_fail;
@@ -252,14 +355,15 @@ static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg,
 		break;
 	case NTLMv2:
 	case RawNTLMSSP:
-		ret = cifs_swn_auth_info_ntlm(tcon, skb);
+		ret = cifs_swn_auth_info_ntlm(swnreg, skb);
 		if (ret < 0) {
 			cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret);
 			goto nlmsg_fail;
 		}
 		break;
 	default:
-		cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype);
+		cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__,
+			 swnreg->auth_type);
 		ret = -EINVAL;
 		goto nlmsg_fail;
 	}
@@ -354,6 +458,17 @@ static void cifs_swn_reg_release(struct cifs_swn_reg *swnreg)
 	if (ret < 0)
 		cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret);
 
+	switch (swnreg->auth_type) {
+	case NTLMv2:
+	case RawNTLMSSP:
+		kfree(swnreg->authinfo.ntlm.user_name);
+		kfree(swnreg->authinfo.ntlm.domain_name);
+		kfree(swnreg->authinfo.ntlm.password);
+		break;
+	default:
+		break;
+	}
+
 	kfree(swnreg->net_name);
 	kfree(swnreg->share_name);
 	kfree(swnreg);
@@ -480,6 +595,13 @@ static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
 		goto fail_net_name;
 	}
 
+	ret = cifs_swn_reg_set_auth(swnreg, tcon);
+	if (ret != 0) {
+		cifs_dbg(VFS, "%s: failed to set auth info: %d\n", __func__,
+			 ret);
+		goto fail_share_name;
+	}
+
 	/*
 	 * If there is an address stored use it instead of the server address, because we are
 	 * in the process of reconnecting to it after a share has been moved or we have been
@@ -506,7 +628,8 @@ static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
 	mutex_unlock(&cifs_swnreg_idr_mutex);
 
 	return swnreg;
-
+fail_share_name:
+	kfree(swnreg->share_name);
 fail_net_name:
 	kfree(swnreg->net_name);
 fail_idr:
-- 
2.54.0


  parent reply	other threads:[~2026-07-10  9:17 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-10  9:16 [PATCH 00/18] SWN: Decouple witness registrations and tcons Samuel Cabrero
2026-07-10  9:16 ` [PATCH 01/18] Revert "smb: client: resolve SWN tcon from live registrations" Samuel Cabrero
2026-07-10  9:16 ` [PATCH 02/18] smb:client: Adjust witness notification request Samuel Cabrero
2026-07-10  9:16 ` [PATCH 03/18] smb:client: Rename variable to match the rest of the code Samuel Cabrero
2026-07-10  9:16 ` [PATCH 04/18] smb:client: Split idr remove and release functions Samuel Cabrero
2026-07-10  9:16 ` [PATCH 05/18] smb:client: Add a specific task to refresh witness registrations Samuel Cabrero
2026-07-10  9:16 ` [PATCH 06/18] smb:client: Store the tcon dstaddr in the witness registration Samuel Cabrero
2026-07-10  9:16 ` [PATCH 07/18] smb:client: Fix printf format string Samuel Cabrero
2026-07-10  9:16 ` [PATCH 08/18] smb:client: Save memory allocations Samuel Cabrero
2026-07-10  9:16 ` [PATCH 09/18] smb:client: Use the correct return code Samuel Cabrero
2026-07-10  9:16 ` [PATCH 10/18] smb:client: Improve tcon matching logic Samuel Cabrero
2026-07-10  9:16 ` [PATCH 11/18] smb:client: Pass the tcon to cifs_swn_send_register_message Samuel Cabrero
2026-07-10  9:16 ` [PATCH 12/18] smb:client: Pass the tcon to notification handlers Samuel Cabrero
2026-07-10  9:16 ` [PATCH 13/18] smb:client: Introduce swn_notification struct Samuel Cabrero
2026-07-10  9:16 ` Samuel Cabrero [this message]
2026-07-10  9:16 ` [PATCH 15/18] smb:client: Do not store the tcon reference, find a matching one Samuel Cabrero
2026-07-10  9:16 ` [PATCH 16/18] smb:client: Simplify registration creation Samuel Cabrero
2026-07-10  9:16 ` [PATCH 17/18] smb:client: Improve registration network and share names handling Samuel Cabrero
2026-07-10  9:16 ` [PATCH 18/18] smb:client: Avoid witness re-register if the address did not change Samuel Cabrero
2026-07-10 14:16 ` [PATCH 00/18] SWN: Decouple witness registrations and tcons Enzo Matsumiya

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260710091637.58873-15-scabrero@suse.com \
    --to=scabrero@suse.com \
    --cc=bharathsm@microsoft.com \
    --cc=ematsumiya@suse.de \
    --cc=henrique.carvalho@suse.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=ronniesahlberg@gmail.com \
    --cc=smfrench@gmail.com \
    --cc=sprasad@microsoft.com \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox