Ronnie Sahlberg | a6a9cff | 2020-10-21 10:22:33 +1000 | [diff] [blame] | 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 | |
Ronnie Sahlberg | 5c6e5aa | 2020-10-21 10:37:11 +1000 | [diff] [blame] | 9 | #include "cifsglob.h" |
| 10 | #include "cifs_debug.h" |
| 11 | #include "fs_context.h" |
| 12 | |
Ronnie Sahlberg | 555782a | 2020-10-21 12:10:44 +1000 | [diff] [blame^] | 13 | static 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 | |
| 27 | int |
| 28 | cifs_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 | |
Ronnie Sahlberg | 5c6e5aa | 2020-10-21 10:37:11 +1000 | [diff] [blame] | 98 | static 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 | |
| 115 | int 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 | } |
Ronnie Sahlberg | 2f20f07 | 2020-10-21 11:30:35 +1000 | [diff] [blame] | 170 | |
| 171 | static 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 | |
| 180 | int |
| 181 | cifs_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 | } |