1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020, Microsoft Corporation.
5 * Author(s): Steve French <stfrench@microsoft.com>
6 * David Howells <dhowells@redhat.com>
10 #include "cifsproto.h"
11 #include "cifs_debug.h"
12 #include "fs_context.h"
14 static const match_table_t cifs_smb_version_tokens = {
15 { Smb_1, SMB1_VERSION_STRING },
16 { Smb_20, SMB20_VERSION_STRING},
17 { Smb_21, SMB21_VERSION_STRING },
18 { Smb_30, SMB30_VERSION_STRING },
19 { Smb_302, SMB302_VERSION_STRING },
20 { Smb_302, ALT_SMB302_VERSION_STRING },
21 { Smb_311, SMB311_VERSION_STRING },
22 { Smb_311, ALT_SMB311_VERSION_STRING },
23 { Smb_3any, SMB3ANY_VERSION_STRING },
24 { Smb_default, SMBDEFAULT_VERSION_STRING },
25 { Smb_version_err, NULL }
29 cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
31 substring_t args[MAX_OPT_ARGS];
33 switch (match_token(value, cifs_smb_version_tokens, args)) {
34 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
36 if (disable_legacy_dialects) {
37 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
41 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
44 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
45 ctx->ops = &smb1_operations;
46 ctx->vals = &smb1_values;
49 if (disable_legacy_dialects) {
50 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
54 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
57 ctx->ops = &smb20_operations;
58 ctx->vals = &smb20_values;
62 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
65 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
67 #endif /* CIFS_ALLOW_INSECURE_LEGACY */
69 ctx->ops = &smb21_operations;
70 ctx->vals = &smb21_values;
73 ctx->ops = &smb30_operations;
74 ctx->vals = &smb30_values;
77 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
78 ctx->vals = &smb302_values;
81 ctx->ops = &smb311_operations;
82 ctx->vals = &smb311_values;
85 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
86 ctx->vals = &smb3any_values;
89 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
90 ctx->vals = &smbdefault_values;
93 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
99 static const match_table_t cifs_secflavor_tokens = {
100 { Opt_sec_krb5, "krb5" },
101 { Opt_sec_krb5i, "krb5i" },
102 { Opt_sec_krb5p, "krb5p" },
103 { Opt_sec_ntlmsspi, "ntlmsspi" },
104 { Opt_sec_ntlmssp, "ntlmssp" },
105 { Opt_ntlm, "ntlm" },
106 { Opt_sec_ntlmi, "ntlmi" },
107 { Opt_sec_ntlmv2, "nontlm" },
108 { Opt_sec_ntlmv2, "ntlmv2" },
109 { Opt_sec_ntlmv2i, "ntlmv2i" },
110 { Opt_sec_lanman, "lanman" },
111 { Opt_sec_none, "none" },
113 { Opt_sec_err, NULL }
116 int cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
119 substring_t args[MAX_OPT_ARGS];
122 * With mount options, the last one should win. Reset any existing
123 * settings back to default.
125 ctx->sectype = Unspecified;
128 switch (match_token(value, cifs_secflavor_tokens, args)) {
130 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
136 ctx->sectype = Kerberos;
138 case Opt_sec_ntlmsspi:
141 case Opt_sec_ntlmssp:
142 ctx->sectype = RawNTLMSSP;
150 case Opt_sec_ntlmv2i:
154 ctx->sectype = NTLMv2;
156 #ifdef CONFIG_CIFS_WEAK_PW_HASH
158 ctx->sectype = LANMAN;
165 cifs_dbg(VFS, "bad security option: %s\n", value);
172 static const match_table_t cifs_cacheflavor_tokens = {
173 { Opt_cache_loose, "loose" },
174 { Opt_cache_strict, "strict" },
175 { Opt_cache_none, "none" },
176 { Opt_cache_ro, "ro" },
177 { Opt_cache_rw, "singleclient" },
178 { Opt_cache_err, NULL }
182 cifs_parse_cache_flavor(char *value, struct smb3_fs_context *ctx)
184 substring_t args[MAX_OPT_ARGS];
186 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
187 case Opt_cache_loose:
188 ctx->direct_io = false;
189 ctx->strict_io = false;
190 ctx->cache_ro = false;
191 ctx->cache_rw = false;
193 case Opt_cache_strict:
194 ctx->direct_io = false;
195 ctx->strict_io = true;
196 ctx->cache_ro = false;
197 ctx->cache_rw = false;
200 ctx->direct_io = true;
201 ctx->strict_io = false;
202 ctx->cache_ro = false;
203 ctx->cache_rw = false;
206 ctx->direct_io = false;
207 ctx->strict_io = false;
208 ctx->cache_ro = true;
209 ctx->cache_rw = false;
212 ctx->direct_io = false;
213 ctx->strict_io = false;
214 ctx->cache_ro = false;
215 ctx->cache_rw = true;
218 cifs_dbg(VFS, "bad cache= option: %s\n", value);
224 #define DUP_CTX_STR(field) \
227 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
228 if (new_ctx->field == NULL) { \
229 cifs_cleanup_volume_info_contents(new_ctx); \
236 smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
240 memcpy(new_ctx, ctx, sizeof(*ctx));
241 new_ctx->prepath = NULL;
242 new_ctx->local_nls = NULL;
243 new_ctx->nodename = NULL;
244 new_ctx->username = NULL;
245 new_ctx->password = NULL;
246 new_ctx->domainname = NULL;
248 new_ctx->iocharset = NULL;
251 * Make sure to stay in sync with cifs_cleanup_volume_info_contents()
253 DUP_CTX_STR(prepath);
254 DUP_CTX_STR(username);
255 DUP_CTX_STR(password);
257 DUP_CTX_STR(domainname);
258 DUP_CTX_STR(nodename);
259 DUP_CTX_STR(iocharset);