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