]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
cifs: Allow to disable or force initialization of NetBIOS session
authorPali Rohár <pali@kernel.org>
Sun, 27 Oct 2024 11:13:12 +0000 (12:13 +0100)
committerSteve French <stfrench@microsoft.com>
Tue, 1 Apr 2025 06:54:17 +0000 (01:54 -0500)
Currently SMB client always tries to initialize NetBIOS session when the
server port is 139. This is useful for default cases, but nowadays when
using non-standard routing or testing between VMs, it is common that
servers are listening on non-standard ports.

So add a new mount option -o nbsessinit and -o nonbsessinit which either
forces initialization or disables initialization regardless of server port
number.

This allows Linux SMB client to connect to older SMB1 server listening on
non-standard port, which requires initialization of NetBIOS session, by
using additional mount options -o port= and -o nbsessinit.

Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h

index 2cb352c16c1ad4d66d5d6e369cfc63fc3fdb62ac..9b0c142c832cf53572d20d8c239dfd49971760a1 100644 (file)
@@ -714,6 +714,7 @@ struct TCP_Server_Info {
        spinlock_t srv_lock;  /* protect anything here that is not protected */
        __u64 conn_id; /* connection identifier (useful for debugging) */
        int srv_count; /* reference counter */
+       int rfc1001_sessinit; /* whether to estasblish netbios session */
        /* 15 character server name + 0x20 16th byte indicating type = srv */
        char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
        struct smb_version_operations   *ops;
index 2349597d5bfcbc0186dfc141f0c40fa6d9935c30..7e2208bd0de75022b6fe54f6ea771e348dd03b62 100644 (file)
@@ -1701,6 +1701,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
                ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
        memcpy(tcp_ses->server_RFC1001_name,
                ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
+       tcp_ses->rfc1001_sessinit = ctx->rfc1001_sessinit;
        tcp_ses->session_estab = false;
        tcp_ses->sequence_number = 0;
        tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
@@ -3328,7 +3329,15 @@ generic_ip_connect(struct TCP_Server_Info *server)
                return rc;
        }
        trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr);
-       if (sport == htons(RFC1001_PORT))
+
+       /*
+        * Establish RFC1001 NetBIOS session when it was explicitly requested
+        * by mount option -o nbsessinit, or when connecting to default RFC1001
+        * server port (139) and it was not explicitly disabled by mount option
+        * -o nonbsessinit.
+        */
+       if (server->rfc1001_sessinit == 1 ||
+           (server->rfc1001_sessinit == -1 && sport == htons(RFC1001_PORT)))
                rc = ip_rfc1001_connect(server);
 
        return rc;
index ed543325c5183ac4e86ce045c9203c0ad304c0a4..2980941b96679c4832dcc2b08b910334a0853ef2 100644 (file)
@@ -135,6 +135,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
        fsparam_flag("witness", Opt_witness),
        fsparam_flag_no("nativesocket", Opt_nativesocket),
        fsparam_flag_no("unicode", Opt_unicode),
+       fsparam_flag_no("nbsessinit", Opt_nbsessinit),
 
        /* Mount options which take uid or gid */
        fsparam_uid("backupuid", Opt_backupuid),
@@ -968,6 +969,10 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
                cifs_errorf(fc, "can not change unicode during remount\n");
                return -EINVAL;
        }
+       if (new_ctx->rfc1001_sessinit != old_ctx->rfc1001_sessinit) {
+               cifs_errorf(fc, "can not change nbsessinit during remount\n");
+               return -EINVAL;
+       }
 
        return 0;
 }
@@ -1609,6 +1614,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                if (i == RFC1001_NAME_LEN && param->string[i] != 0)
                        pr_warn("server netbiosname longer than 15 truncated\n");
                break;
+       case Opt_nbsessinit:
+               ctx->rfc1001_sessinit = !result.negated;
+               cifs_dbg(FYI, "rfc1001_sessinit set to %d\n", ctx->rfc1001_sessinit);
+               break;
        case Opt_ver:
                /* version of mount userspace tools, not dialect */
                /* If interface changes in mount.cifs bump to new ver */
@@ -1896,13 +1905,16 @@ int smb3_init_fs_context(struct fs_context *fc)
        memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
        for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
                ctx->source_rfc1001_name[i] = toupper(nodename[i]);
-
        ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
+
        /*
         * null target name indicates to use *SMBSERVR default called name
         *  if we end up sending RFC1001 session initialize
         */
        ctx->target_rfc1001_name[0] = 0;
+
+       ctx->rfc1001_sessinit = -1; /* autodetect based on port number */
+
        ctx->cred_uid = current_uid();
        ctx->linux_uid = current_uid();
        ctx->linux_gid = current_gid();
index 23491401dac5ef5a12728f3c7fd0e9dd99f53539..d1d29249bcdb97ee4846342ee3ca440cdf08cfe9 100644 (file)
@@ -174,6 +174,7 @@ enum cifs_param {
        Opt_iocharset,
        Opt_netbiosname,
        Opt_servern,
+       Opt_nbsessinit,
        Opt_ver,
        Opt_vers,
        Opt_sec,
@@ -216,6 +217,7 @@ struct smb3_fs_context {
        char *iocharset;  /* local code page for mapping to and from Unicode */
        char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
        char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
+       int rfc1001_sessinit;
        kuid_t cred_uid;
        kuid_t linux_uid;
        kgid_t linux_gid;