From patchwork Thu Apr 4 23:19:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 13618287 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B21A70CC2 for ; Thu, 4 Apr 2024 23:19:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712272786; cv=none; b=nNCG6JscE9gHGXyQIUwis2IKdrlnUyM+l0WxO8MH2GZ9k71Y5Zpqf5VuhcXO82iJhNJah64LAKPhBhQOTv0eyuP4816zJtSvC7G8xyi963EGVS0FiKXv8ksTi0wsTsTHy3kb2pN+zJzENZ7hT+jdiVKzLAoghw3XnkD5EU7ym3U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712272786; c=relaxed/simple; bh=dpWEnpzpON8xS6rT/tE8OhCBEyqRZKJbo//8yKcBkw0=; h=MIME-Version:From:Date:Message-ID:Subject:To:Cc:Content-Type; b=ZbF8jLio7+8JeaYO4ubg8uz/rhs6XrvP+ulQwV8Wn46koAlGLYfokt1cYq2gMmSUmx09zq9anf9ejSN0arxc0dEa9lMbG+VsS2C7IxClVEeY10A6i4x7d+4f9VpZw41TxxNNv3ueVMNhEh2EfiRE0E3F3EPDwi3+p7kRStUj/LA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=A8enGNT6; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="A8enGNT6" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-516c5c39437so2032332e87.1 for ; Thu, 04 Apr 2024 16:19:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712272782; x=1712877582; darn=vger.kernel.org; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=MI+qfzpviQ6203tqR2NcHQB0VPCJX0zA2qLw4gc27aE=; b=A8enGNT61Obgf98alSc4I7sW7VAq/lzBrvdhB3GN+OM45UhBB3KFNHw2dodaiJ7zvO pDNHuGGWhqXL8v0BrzVm6sGI5q1r4uqaHs6K1F71QsOYiAFiMf0s64rcgndhCY6q+QMS WjfmZ9QqtDF+vkU2kR0IdwLAqnHGF5D+TEctFEk5SHjiyN/+6ItXhdf4p7jPtwvg1lPS voN05iKX2C97D3qenc1qJTlivIRHJmkkBrxHf4KR7coiQgKm3Wbteyoz7iyu6hn06NcA TF0zzJzai29TVbXOSSLfwC91rxLk32JuIa/EBAL8yPxKDXwFNRCoNXKvYgrstt7g0IJ8 55zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712272782; x=1712877582; h=cc:to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=MI+qfzpviQ6203tqR2NcHQB0VPCJX0zA2qLw4gc27aE=; b=F1el+kDyuNW8haQU1UAmSx86297mBacjtd3P3bJvlNnJGd99HQJPT32Msmiapr2fQE 9gmTffDA7N4vceQbeP0wiMakInu0WBPZFL9YKk2jP4fZeEi/yY6uqEPeM8RYao+4ENZQ Fa5YA7rwkrHsULjfL+A6frLXif2Q3gzwNMC+8pTgNS6+i814Vo8Jg0yv8xMfW4X6L2e7 jrnpcnIt4fKQh/C22rqBLFDb64tkfRcl6+jfc8oY0pv+4obAH7ZXTWOZ2ujy1OoGwqvn OqNmVFf2nloSpx8enKp7zbP/03ZMbDeAiDlPCeyWnL2cHR4LfcL4HpVFbuNwXvxmyvPL FBIg== X-Gm-Message-State: AOJu0YyoDcmyXEUJipJbmKT3PeJAbpV5q8G9MOJnL5WWwrdD0+gbRlvB JoAKpmfl1in3mp8AFfLn+YOqdEc/cKGBNW8PgY3rOxriDs22URUj6iVqkPl9iQf5nvbGLnqQXQc MP9EI8boYtfbXheLX+yhnPgk1LV+aO692//w= X-Google-Smtp-Source: AGHT+IGsWQ/1HQwj1pPWVAc2ZoaY1jNoziM7NldhkFE5iaMyf9zKAZVqVUMvGzOt/TorXz22eJZIO2qwgc8Q1yRbMlI= X-Received: by 2002:a19:c203:0:b0:516:d14a:9692 with SMTP id l3-20020a19c203000000b00516d14a9692mr1298685lfc.6.1712272781876; Thu, 04 Apr 2024 16:19:41 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-cifs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steve French Date: Thu, 4 Apr 2024 18:19:30 -0500 Message-ID: Subject: [SMB3] fix reconnect so it can handle cases where server is doing password rotation To: CIFS , samba-technical Cc: Shyam Prasad N , Tom Talpey , Bharath S M There are various use cases that are becoming more common in which password changes are scheduled on a server(s) periodically but the clients connected to this server need to stay connected (even in the face of brief network reconnects) due to mounts which can not be easily unmounted and mounted at will, and servers that do password rotation do not always have the ability to tell the clients exactly when to the new password will be effective, so add support for an alt password ("password2=") on mount (and also remount) so that we can anticipate the upcoming change to the server without risking breaking existing mounts. An alternative would have been to use the kernel keyring for this but the processes doing the reconnect does not have access to the keyring but does have access to the ses structure. See attached Linux client patch From aef510318e3841a4ad3bba78c5f8e1077a0f5b09 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 4 Apr 2024 18:06:56 -0500 Subject: [PATCH] smb3: fix broken reconnect when password changing on the server by allowing password rotation There are various use cases that are becoming more common in which password changes are scheduled on a server(s) periodically but the clients connected to this server need to stay connected (even in the face of brief network reconnects) due to mounts which can not be easily unmounted and mounted at will, and servers that do password rotation do not always have the ability to tell the clients exactly when to the new password will be effective, so add support for an alt password ("password2=") on mount (and also remount) so that we can anticipate the upcoming change to the server without risking breaking existing mounts. An alternative would have been to use the kernel keyring for this but the processes doing the reconnect does not have access to the keyring but does have access to the ses structure. Signed-off-by: Steve French --- fs/smb/client/cifsglob.h | 1 + fs/smb/client/connect.c | 8 ++++++++ fs/smb/client/fs_context.c | 21 +++++++++++++++++++++ fs/smb/client/fs_context.h | 2 ++ fs/smb/client/misc.c | 1 + fs/smb/client/smb2pdu.c | 11 +++++++++++ 6 files changed, 44 insertions(+) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index f6a302205f89..9e02f27ef70f 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1077,6 +1077,7 @@ struct cifs_ses { and after mount option parsing we fill it */ char *domainName; char *password; + char *password2; /* When key rotation used, new password may be set before it expires */ char workstation_name[CIFS_MAX_WORKSTATION_LEN]; struct session_key auth_key; struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 85679ae106fd..4e35970681bf 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -2183,6 +2183,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) } ++delim; + /* BB consider adding support for password2 (Key Rotation) for multiuser in future */ ctx->password = kstrndup(delim, len, GFP_KERNEL); if (!ctx->password) { cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n", @@ -2206,6 +2207,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) kfree(ctx->username); ctx->username = NULL; kfree_sensitive(ctx->password); + /* no need to free ctx->password2 since not allocated in this path */ ctx->password = NULL; goto out_key_put; } @@ -2317,6 +2319,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) if (!ses->password) goto get_ses_fail; } + /* ctx->password freed at unmount */ + if (ctx->password2) { + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); + if (!ses->password2) + goto get_ses_fail; + } if (ctx->domainname) { ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL); if (!ses->domainName) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index b7bfe705b2c4..6c727d8c31e8 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -162,6 +162,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_string("username", Opt_user), fsparam_string("pass", Opt_pass), fsparam_string("password", Opt_pass), + fsparam_string("password2", Opt_pass2), fsparam_string("ip", Opt_ip), fsparam_string("addr", Opt_ip), fsparam_string("domain", Opt_domain), @@ -345,6 +346,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx new_ctx->nodename = NULL; new_ctx->username = NULL; new_ctx->password = NULL; + new_ctx->password2 = NULL; new_ctx->server_hostname = NULL; new_ctx->domainname = NULL; new_ctx->UNC = NULL; @@ -357,6 +359,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx DUP_CTX_STR(prepath); DUP_CTX_STR(username); DUP_CTX_STR(password); + DUP_CTX_STR(password2); DUP_CTX_STR(server_hostname); DUP_CTX_STR(UNC); DUP_CTX_STR(source); @@ -905,6 +908,8 @@ static int smb3_reconfigure(struct fs_context *fc) else { kfree_sensitive(ses->password); ses->password = kstrdup(ctx->password, GFP_KERNEL); + kfree_sensitive(ses->password2); + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); } STEAL_STRING(cifs_sb, ctx, domainname); STEAL_STRING(cifs_sb, ctx, nodename); @@ -1305,6 +1310,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, goto cifs_parse_mount_err; } break; + case Opt_pass2: + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; + if (strlen(param->string) == 0) + break; + + ctx->password2 = kstrdup(param->string, GFP_KERNEL); + if (ctx->password2 == NULL) { + cifs_errorf(fc, "OOM when copying password2 string\n"); + goto cifs_parse_mount_err; + } + break; case Opt_ip: if (strlen(param->string) == 0) { ctx->got_ip = false; @@ -1608,6 +1625,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, cifs_parse_mount_err: kfree_sensitive(ctx->password); ctx->password = NULL; + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; return -EINVAL; } @@ -1713,6 +1732,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) ctx->username = NULL; kfree_sensitive(ctx->password); ctx->password = NULL; + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; kfree(ctx->server_hostname); ctx->server_hostname = NULL; kfree(ctx->UNC); diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index 8a35645e0b65..a947bddeba27 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h @@ -145,6 +145,7 @@ enum cifs_param { Opt_source, Opt_user, Opt_pass, + Opt_pass2, Opt_ip, Opt_domain, Opt_srcaddr, @@ -177,6 +178,7 @@ struct smb3_fs_context { char *username; char *password; + char *password2; char *domainname; char *source; char *server_hostname; diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 33ac4f8f5050..7d15a1969b81 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -98,6 +98,7 @@ sesInfoFree(struct cifs_ses *buf_to_free) kfree(buf_to_free->serverDomain); kfree(buf_to_free->serverNOS); kfree_sensitive(buf_to_free->password); + kfree_sensitive(buf_to_free->password2); kfree(buf_to_free->user_name); kfree(buf_to_free->domainName); kfree_sensitive(buf_to_free->auth_key.response); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index c0c4933af5fc..86c647a947cc 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -367,6 +367,17 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, } rc = cifs_setup_session(0, ses, server, nls_codepage); + if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) { + /* + * Try alternate password for next reconnect (key rotation + * could be enabled on the server e.g.) if an alternate + * password is available and the current password is expired, + * but do not swap on non pwd related errors like host down + */ + if (ses->password2) + swap(ses->password2, ses->password); + } + if ((rc == -EACCES) && !tcon->retry) { mutex_unlock(&ses->session_mutex); rc = -EHOSTDOWN; -- 2.40.1