18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *   Copyright (C) 2020, Microsoft Corporation.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *   Author(s): Steve French <stfrench@microsoft.com>
68c2ecf20Sopenharmony_ci *              David Howells <dhowells@redhat.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "cifsglob.h"
108c2ecf20Sopenharmony_ci#include "cifs_debug.h"
118c2ecf20Sopenharmony_ci#include "fs_context.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic const match_table_t cifs_smb_version_tokens = {
148c2ecf20Sopenharmony_ci	{ Smb_1, SMB1_VERSION_STRING },
158c2ecf20Sopenharmony_ci	{ Smb_20, SMB20_VERSION_STRING},
168c2ecf20Sopenharmony_ci	{ Smb_21, SMB21_VERSION_STRING },
178c2ecf20Sopenharmony_ci	{ Smb_30, SMB30_VERSION_STRING },
188c2ecf20Sopenharmony_ci	{ Smb_302, SMB302_VERSION_STRING },
198c2ecf20Sopenharmony_ci	{ Smb_302, ALT_SMB302_VERSION_STRING },
208c2ecf20Sopenharmony_ci	{ Smb_311, SMB311_VERSION_STRING },
218c2ecf20Sopenharmony_ci	{ Smb_311, ALT_SMB311_VERSION_STRING },
228c2ecf20Sopenharmony_ci	{ Smb_3any, SMB3ANY_VERSION_STRING },
238c2ecf20Sopenharmony_ci	{ Smb_default, SMBDEFAULT_VERSION_STRING },
248c2ecf20Sopenharmony_ci	{ Smb_version_err, NULL }
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciint
288c2ecf20Sopenharmony_cicifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	switch (match_token(value, cifs_smb_version_tokens, args)) {
338c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
348c2ecf20Sopenharmony_ci	case Smb_1:
358c2ecf20Sopenharmony_ci		if (disable_legacy_dialects) {
368c2ecf20Sopenharmony_ci			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
378c2ecf20Sopenharmony_ci			return 1;
388c2ecf20Sopenharmony_ci		}
398c2ecf20Sopenharmony_ci		if (is_smb3) {
408c2ecf20Sopenharmony_ci			cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
418c2ecf20Sopenharmony_ci			return 1;
428c2ecf20Sopenharmony_ci		}
438c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
448c2ecf20Sopenharmony_ci		vol->ops = &smb1_operations;
458c2ecf20Sopenharmony_ci		vol->vals = &smb1_values;
468c2ecf20Sopenharmony_ci		break;
478c2ecf20Sopenharmony_ci	case Smb_20:
488c2ecf20Sopenharmony_ci		if (disable_legacy_dialects) {
498c2ecf20Sopenharmony_ci			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
508c2ecf20Sopenharmony_ci			return 1;
518c2ecf20Sopenharmony_ci		}
528c2ecf20Sopenharmony_ci		if (is_smb3) {
538c2ecf20Sopenharmony_ci			cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
548c2ecf20Sopenharmony_ci			return 1;
558c2ecf20Sopenharmony_ci		}
568c2ecf20Sopenharmony_ci		vol->ops = &smb20_operations;
578c2ecf20Sopenharmony_ci		vol->vals = &smb20_values;
588c2ecf20Sopenharmony_ci		break;
598c2ecf20Sopenharmony_ci#else
608c2ecf20Sopenharmony_ci	case Smb_1:
618c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
628c2ecf20Sopenharmony_ci		return 1;
638c2ecf20Sopenharmony_ci	case Smb_20:
648c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
658c2ecf20Sopenharmony_ci		return 1;
668c2ecf20Sopenharmony_ci#endif /* CIFS_ALLOW_INSECURE_LEGACY */
678c2ecf20Sopenharmony_ci	case Smb_21:
688c2ecf20Sopenharmony_ci		vol->ops = &smb21_operations;
698c2ecf20Sopenharmony_ci		vol->vals = &smb21_values;
708c2ecf20Sopenharmony_ci		break;
718c2ecf20Sopenharmony_ci	case Smb_30:
728c2ecf20Sopenharmony_ci		vol->ops = &smb30_operations;
738c2ecf20Sopenharmony_ci		vol->vals = &smb30_values;
748c2ecf20Sopenharmony_ci		break;
758c2ecf20Sopenharmony_ci	case Smb_302:
768c2ecf20Sopenharmony_ci		vol->ops = &smb30_operations; /* currently identical with 3.0 */
778c2ecf20Sopenharmony_ci		vol->vals = &smb302_values;
788c2ecf20Sopenharmony_ci		break;
798c2ecf20Sopenharmony_ci	case Smb_311:
808c2ecf20Sopenharmony_ci		vol->ops = &smb311_operations;
818c2ecf20Sopenharmony_ci		vol->vals = &smb311_values;
828c2ecf20Sopenharmony_ci		break;
838c2ecf20Sopenharmony_ci	case Smb_3any:
848c2ecf20Sopenharmony_ci		vol->ops = &smb30_operations; /* currently identical with 3.0 */
858c2ecf20Sopenharmony_ci		vol->vals = &smb3any_values;
868c2ecf20Sopenharmony_ci		break;
878c2ecf20Sopenharmony_ci	case Smb_default:
888c2ecf20Sopenharmony_ci		vol->ops = &smb30_operations; /* currently identical with 3.0 */
898c2ecf20Sopenharmony_ci		vol->vals = &smbdefault_values;
908c2ecf20Sopenharmony_ci		break;
918c2ecf20Sopenharmony_ci	default:
928c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
938c2ecf20Sopenharmony_ci		return 1;
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci	return 0;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic const match_table_t cifs_secflavor_tokens = {
998c2ecf20Sopenharmony_ci	{ Opt_sec_krb5, "krb5" },
1008c2ecf20Sopenharmony_ci	{ Opt_sec_krb5i, "krb5i" },
1018c2ecf20Sopenharmony_ci	{ Opt_sec_krb5p, "krb5p" },
1028c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmsspi, "ntlmsspi" },
1038c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmssp, "ntlmssp" },
1048c2ecf20Sopenharmony_ci	{ Opt_ntlm, "ntlm" },
1058c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmi, "ntlmi" },
1068c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmv2, "nontlm" },
1078c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmv2, "ntlmv2" },
1088c2ecf20Sopenharmony_ci	{ Opt_sec_ntlmv2i, "ntlmv2i" },
1098c2ecf20Sopenharmony_ci	{ Opt_sec_lanman, "lanman" },
1108c2ecf20Sopenharmony_ci	{ Opt_sec_none, "none" },
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	{ Opt_sec_err, NULL }
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciint cifs_parse_security_flavors(char *value, struct smb_vol *vol)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/*
1218c2ecf20Sopenharmony_ci	 * With mount options, the last one should win. Reset any existing
1228c2ecf20Sopenharmony_ci	 * settings back to default.
1238c2ecf20Sopenharmony_ci	 */
1248c2ecf20Sopenharmony_ci	vol->sectype = Unspecified;
1258c2ecf20Sopenharmony_ci	vol->sign = false;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	switch (match_token(value, cifs_secflavor_tokens, args)) {
1288c2ecf20Sopenharmony_ci	case Opt_sec_krb5p:
1298c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1308c2ecf20Sopenharmony_ci		return 1;
1318c2ecf20Sopenharmony_ci	case Opt_sec_krb5i:
1328c2ecf20Sopenharmony_ci		vol->sign = true;
1338c2ecf20Sopenharmony_ci		fallthrough;
1348c2ecf20Sopenharmony_ci	case Opt_sec_krb5:
1358c2ecf20Sopenharmony_ci		vol->sectype = Kerberos;
1368c2ecf20Sopenharmony_ci		break;
1378c2ecf20Sopenharmony_ci	case Opt_sec_ntlmsspi:
1388c2ecf20Sopenharmony_ci		vol->sign = true;
1398c2ecf20Sopenharmony_ci		fallthrough;
1408c2ecf20Sopenharmony_ci	case Opt_sec_ntlmssp:
1418c2ecf20Sopenharmony_ci		vol->sectype = RawNTLMSSP;
1428c2ecf20Sopenharmony_ci		break;
1438c2ecf20Sopenharmony_ci	case Opt_sec_ntlmi:
1448c2ecf20Sopenharmony_ci		vol->sign = true;
1458c2ecf20Sopenharmony_ci		fallthrough;
1468c2ecf20Sopenharmony_ci	case Opt_ntlm:
1478c2ecf20Sopenharmony_ci		vol->sectype = NTLM;
1488c2ecf20Sopenharmony_ci		break;
1498c2ecf20Sopenharmony_ci	case Opt_sec_ntlmv2i:
1508c2ecf20Sopenharmony_ci		vol->sign = true;
1518c2ecf20Sopenharmony_ci		fallthrough;
1528c2ecf20Sopenharmony_ci	case Opt_sec_ntlmv2:
1538c2ecf20Sopenharmony_ci		vol->sectype = NTLMv2;
1548c2ecf20Sopenharmony_ci		break;
1558c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_WEAK_PW_HASH
1568c2ecf20Sopenharmony_ci	case Opt_sec_lanman:
1578c2ecf20Sopenharmony_ci		vol->sectype = LANMAN;
1588c2ecf20Sopenharmony_ci		break;
1598c2ecf20Sopenharmony_ci#endif
1608c2ecf20Sopenharmony_ci	case Opt_sec_none:
1618c2ecf20Sopenharmony_ci		vol->nullauth = 1;
1628c2ecf20Sopenharmony_ci		break;
1638c2ecf20Sopenharmony_ci	default:
1648c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "bad security option: %s\n", value);
1658c2ecf20Sopenharmony_ci		return 1;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	return 0;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic const match_table_t cifs_cacheflavor_tokens = {
1728c2ecf20Sopenharmony_ci	{ Opt_cache_loose, "loose" },
1738c2ecf20Sopenharmony_ci	{ Opt_cache_strict, "strict" },
1748c2ecf20Sopenharmony_ci	{ Opt_cache_none, "none" },
1758c2ecf20Sopenharmony_ci	{ Opt_cache_ro, "ro" },
1768c2ecf20Sopenharmony_ci	{ Opt_cache_rw, "singleclient" },
1778c2ecf20Sopenharmony_ci	{ Opt_cache_err, NULL }
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ciint
1818c2ecf20Sopenharmony_cicifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1868c2ecf20Sopenharmony_ci	case Opt_cache_loose:
1878c2ecf20Sopenharmony_ci		vol->direct_io = false;
1888c2ecf20Sopenharmony_ci		vol->strict_io = false;
1898c2ecf20Sopenharmony_ci		vol->cache_ro = false;
1908c2ecf20Sopenharmony_ci		vol->cache_rw = false;
1918c2ecf20Sopenharmony_ci		break;
1928c2ecf20Sopenharmony_ci	case Opt_cache_strict:
1938c2ecf20Sopenharmony_ci		vol->direct_io = false;
1948c2ecf20Sopenharmony_ci		vol->strict_io = true;
1958c2ecf20Sopenharmony_ci		vol->cache_ro = false;
1968c2ecf20Sopenharmony_ci		vol->cache_rw = false;
1978c2ecf20Sopenharmony_ci		break;
1988c2ecf20Sopenharmony_ci	case Opt_cache_none:
1998c2ecf20Sopenharmony_ci		vol->direct_io = true;
2008c2ecf20Sopenharmony_ci		vol->strict_io = false;
2018c2ecf20Sopenharmony_ci		vol->cache_ro = false;
2028c2ecf20Sopenharmony_ci		vol->cache_rw = false;
2038c2ecf20Sopenharmony_ci		break;
2048c2ecf20Sopenharmony_ci	case Opt_cache_ro:
2058c2ecf20Sopenharmony_ci		vol->direct_io = false;
2068c2ecf20Sopenharmony_ci		vol->strict_io = false;
2078c2ecf20Sopenharmony_ci		vol->cache_ro = true;
2088c2ecf20Sopenharmony_ci		vol->cache_rw = false;
2098c2ecf20Sopenharmony_ci		break;
2108c2ecf20Sopenharmony_ci	case Opt_cache_rw:
2118c2ecf20Sopenharmony_ci		vol->direct_io = false;
2128c2ecf20Sopenharmony_ci		vol->strict_io = false;
2138c2ecf20Sopenharmony_ci		vol->cache_ro = false;
2148c2ecf20Sopenharmony_ci		vol->cache_rw = true;
2158c2ecf20Sopenharmony_ci		break;
2168c2ecf20Sopenharmony_ci	default:
2178c2ecf20Sopenharmony_ci		cifs_dbg(VFS, "bad cache= option: %s\n", value);
2188c2ecf20Sopenharmony_ci		return 1;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci	return 0;
2218c2ecf20Sopenharmony_ci}
222