xref: /kernel/linux/linux-5.10/fs/cifs/fs_context.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *   Copyright (C) 2020, Microsoft Corporation.
4 *
5 *   Author(s): Steve French <stfrench@microsoft.com>
6 *              David Howells <dhowells@redhat.com>
7 */
8
9#include "cifsglob.h"
10#include "cifs_debug.h"
11#include "fs_context.h"
12
13static const match_table_t cifs_smb_version_tokens = {
14	{ Smb_1, SMB1_VERSION_STRING },
15	{ Smb_20, SMB20_VERSION_STRING},
16	{ Smb_21, SMB21_VERSION_STRING },
17	{ Smb_30, SMB30_VERSION_STRING },
18	{ Smb_302, SMB302_VERSION_STRING },
19	{ Smb_302, ALT_SMB302_VERSION_STRING },
20	{ Smb_311, SMB311_VERSION_STRING },
21	{ Smb_311, ALT_SMB311_VERSION_STRING },
22	{ Smb_3any, SMB3ANY_VERSION_STRING },
23	{ Smb_default, SMBDEFAULT_VERSION_STRING },
24	{ Smb_version_err, NULL }
25};
26
27int
28cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
29{
30	substring_t args[MAX_OPT_ARGS];
31
32	switch (match_token(value, cifs_smb_version_tokens, args)) {
33#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
34	case Smb_1:
35		if (disable_legacy_dialects) {
36			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
37			return 1;
38		}
39		if (is_smb3) {
40			cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
41			return 1;
42		}
43		cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
44		vol->ops = &smb1_operations;
45		vol->vals = &smb1_values;
46		break;
47	case Smb_20:
48		if (disable_legacy_dialects) {
49			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
50			return 1;
51		}
52		if (is_smb3) {
53			cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
54			return 1;
55		}
56		vol->ops = &smb20_operations;
57		vol->vals = &smb20_values;
58		break;
59#else
60	case Smb_1:
61		cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
62		return 1;
63	case Smb_20:
64		cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
65		return 1;
66#endif /* CIFS_ALLOW_INSECURE_LEGACY */
67	case Smb_21:
68		vol->ops = &smb21_operations;
69		vol->vals = &smb21_values;
70		break;
71	case Smb_30:
72		vol->ops = &smb30_operations;
73		vol->vals = &smb30_values;
74		break;
75	case Smb_302:
76		vol->ops = &smb30_operations; /* currently identical with 3.0 */
77		vol->vals = &smb302_values;
78		break;
79	case Smb_311:
80		vol->ops = &smb311_operations;
81		vol->vals = &smb311_values;
82		break;
83	case Smb_3any:
84		vol->ops = &smb30_operations; /* currently identical with 3.0 */
85		vol->vals = &smb3any_values;
86		break;
87	case Smb_default:
88		vol->ops = &smb30_operations; /* currently identical with 3.0 */
89		vol->vals = &smbdefault_values;
90		break;
91	default:
92		cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
93		return 1;
94	}
95	return 0;
96}
97
98static const match_table_t cifs_secflavor_tokens = {
99	{ Opt_sec_krb5, "krb5" },
100	{ Opt_sec_krb5i, "krb5i" },
101	{ Opt_sec_krb5p, "krb5p" },
102	{ Opt_sec_ntlmsspi, "ntlmsspi" },
103	{ Opt_sec_ntlmssp, "ntlmssp" },
104	{ Opt_ntlm, "ntlm" },
105	{ Opt_sec_ntlmi, "ntlmi" },
106	{ Opt_sec_ntlmv2, "nontlm" },
107	{ Opt_sec_ntlmv2, "ntlmv2" },
108	{ Opt_sec_ntlmv2i, "ntlmv2i" },
109	{ Opt_sec_lanman, "lanman" },
110	{ Opt_sec_none, "none" },
111
112	{ Opt_sec_err, NULL }
113};
114
115int cifs_parse_security_flavors(char *value, struct smb_vol *vol)
116{
117
118	substring_t args[MAX_OPT_ARGS];
119
120	/*
121	 * With mount options, the last one should win. Reset any existing
122	 * settings back to default.
123	 */
124	vol->sectype = Unspecified;
125	vol->sign = false;
126
127	switch (match_token(value, cifs_secflavor_tokens, args)) {
128	case Opt_sec_krb5p:
129		cifs_dbg(VFS, "sec=krb5p is not supported!\n");
130		return 1;
131	case Opt_sec_krb5i:
132		vol->sign = true;
133		fallthrough;
134	case Opt_sec_krb5:
135		vol->sectype = Kerberos;
136		break;
137	case Opt_sec_ntlmsspi:
138		vol->sign = true;
139		fallthrough;
140	case Opt_sec_ntlmssp:
141		vol->sectype = RawNTLMSSP;
142		break;
143	case Opt_sec_ntlmi:
144		vol->sign = true;
145		fallthrough;
146	case Opt_ntlm:
147		vol->sectype = NTLM;
148		break;
149	case Opt_sec_ntlmv2i:
150		vol->sign = true;
151		fallthrough;
152	case Opt_sec_ntlmv2:
153		vol->sectype = NTLMv2;
154		break;
155#ifdef CONFIG_CIFS_WEAK_PW_HASH
156	case Opt_sec_lanman:
157		vol->sectype = LANMAN;
158		break;
159#endif
160	case Opt_sec_none:
161		vol->nullauth = 1;
162		break;
163	default:
164		cifs_dbg(VFS, "bad security option: %s\n", value);
165		return 1;
166	}
167
168	return 0;
169}
170
171static const match_table_t cifs_cacheflavor_tokens = {
172	{ Opt_cache_loose, "loose" },
173	{ Opt_cache_strict, "strict" },
174	{ Opt_cache_none, "none" },
175	{ Opt_cache_ro, "ro" },
176	{ Opt_cache_rw, "singleclient" },
177	{ Opt_cache_err, NULL }
178};
179
180int
181cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
182{
183	substring_t args[MAX_OPT_ARGS];
184
185	switch (match_token(value, cifs_cacheflavor_tokens, args)) {
186	case Opt_cache_loose:
187		vol->direct_io = false;
188		vol->strict_io = false;
189		vol->cache_ro = false;
190		vol->cache_rw = false;
191		break;
192	case Opt_cache_strict:
193		vol->direct_io = false;
194		vol->strict_io = true;
195		vol->cache_ro = false;
196		vol->cache_rw = false;
197		break;
198	case Opt_cache_none:
199		vol->direct_io = true;
200		vol->strict_io = false;
201		vol->cache_ro = false;
202		vol->cache_rw = false;
203		break;
204	case Opt_cache_ro:
205		vol->direct_io = false;
206		vol->strict_io = false;
207		vol->cache_ro = true;
208		vol->cache_rw = false;
209		break;
210	case Opt_cache_rw:
211		vol->direct_io = false;
212		vol->strict_io = false;
213		vol->cache_ro = false;
214		vol->cache_rw = true;
215		break;
216	default:
217		cifs_dbg(VFS, "bad cache= option: %s\n", value);
218		return 1;
219	}
220	return 0;
221}
222