Commit e4aa25e7801163df058f62c617b859e9d3d4b148

Authored by Steve French
1 parent c052e2b423

[CIFS] Fix SMB2 negotiation support to select only one dialect (based on vers=)

Based on whether the user (on mount command) chooses:

vers=3.0 (for smb3.0 support)
vers=2.1 (for smb2.1 support)
or (with subsequent patch, which will allow SMB2 support)
vers=2.0 (for original smb2.02 dialect support)

send only one dialect at a time during negotiate (we
had been sending a list).

Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>

Showing 5 changed files with 56 additions and 29 deletions Side-by-side Diff

... ... @@ -179,6 +179,7 @@
179 179 enum smb_version {
180 180 Smb_1 = 1,
181 181 Smb_21,
  182 + Smb_30,
182 183 };
183 184  
184 185 struct mid_q_entry;
... ... @@ -372,6 +373,8 @@
372 373  
373 374 struct smb_version_values {
374 375 char *version_string;
  376 + __u16 protocol_id;
  377 + __u32 req_capabilities;
375 378 __u32 large_lock_type;
376 379 __u32 exclusive_lock_type;
377 380 __u32 shared_lock_type;
378 381  
... ... @@ -1496,8 +1499,14 @@
1496 1499 #define SMB1_VERSION_STRING "1.0"
1497 1500 extern struct smb_version_operations smb1_operations;
1498 1501 extern struct smb_version_values smb1_values;
  1502 +#define SMB20_VERSION_STRING "2.0"
  1503 +/*extern struct smb_version_operations smb20_operations; */ /* not needed yet */
  1504 +extern struct smb_version_values smb20_values;
1499 1505 #define SMB21_VERSION_STRING "2.1"
1500 1506 extern struct smb_version_operations smb21_operations;
1501 1507 extern struct smb_version_values smb21_values;
  1508 +#define SMB30_VERSION_STRING "3.0"
  1509 +/*extern struct smb_version_operations smb30_operations; */ /* not needed yet */
  1510 +extern struct smb_version_values smb30_values;
1502 1511 #endif /* _CIFS_GLOB_H */
... ... @@ -272,6 +272,7 @@
272 272 static const match_table_t cifs_smb_version_tokens = {
273 273 { Smb_1, SMB1_VERSION_STRING },
274 274 { Smb_21, SMB21_VERSION_STRING },
  275 + { Smb_30, SMB30_VERSION_STRING },
275 276 };
276 277  
277 278 static int ip_connect(struct TCP_Server_Info *server);
... ... @@ -1073,6 +1074,10 @@
1073 1074 case Smb_21:
1074 1075 vol->ops = &smb21_operations;
1075 1076 vol->vals = &smb21_values;
  1077 + break;
  1078 + case Smb_30:
  1079 + vol->ops = &smb21_operations; /* currently identical with 2.1 */
  1080 + vol->vals = &smb30_values;
1076 1081 break;
1077 1082 #endif
1078 1083 default:
... ... @@ -645,6 +645,25 @@
645 645  
646 646 struct smb_version_values smb21_values = {
647 647 .version_string = SMB21_VERSION_STRING,
  648 + .protocol_id = SMB21_PROT_ID,
  649 + .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
  650 + .large_lock_type = 0,
  651 + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  652 + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  653 + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
  654 + .header_size = sizeof(struct smb2_hdr),
  655 + .max_header_size = MAX_SMB2_HDR_SIZE,
  656 + .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
  657 + .lock_cmd = SMB2_LOCK,
  658 + .cap_unix = 0,
  659 + .cap_nt_find = SMB2_NT_FIND,
  660 + .cap_large_files = SMB2_LARGE_FILES,
  661 +};
  662 +
  663 +struct smb_version_values smb30_values = {
  664 + .version_string = SMB30_VERSION_STRING,
  665 + .protocol_id = SMB30_PROT_ID,
  666 + .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
648 667 .large_lock_type = 0,
649 668 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
650 669 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
1 1 /*
2 2 * fs/cifs/smb2pdu.c
3 3 *
4   - * Copyright (C) International Business Machines Corp., 2009, 2011
  4 + * Copyright (C) International Business Machines Corp., 2009, 2012
5 5 * Etersoft, 2012
6 6 * Author(s): Steve French (sfrench@us.ibm.com)
7 7 * Pavel Shilovsky (pshilovsky@samba.org) 2012
8 8  
... ... @@ -304,25 +304,7 @@
304 304 cifs_buf_release(rsp);
305 305 }
306 306  
307   -#define SMB2_NUM_PROT 2
308 307  
309   -#define SMB2_PROT 0
310   -#define SMB21_PROT 1
311   -#define BAD_PROT 0xFFFF
312   -
313   -#define SMB2_PROT_ID 0x0202
314   -#define SMB21_PROT_ID 0x0210
315   -#define BAD_PROT_ID 0xFFFF
316   -
317   -static struct {
318   - int index;
319   - __le16 name;
320   -} smb2protocols[] = {
321   - {SMB2_PROT, cpu_to_le16(SMB2_PROT_ID)},
322   - {SMB21_PROT, cpu_to_le16(SMB21_PROT_ID)},
323   - {BAD_PROT, cpu_to_le16(BAD_PROT_ID)}
324   -};
325   -
326 308 /*
327 309 *
328 310 * SMB2 Worker functions follow:
... ... @@ -348,7 +330,6 @@
348 330 int resp_buftype;
349 331 struct TCP_Server_Info *server;
350 332 unsigned int sec_flags;
351   - u16 i;
352 333 u16 temp = 0;
353 334 int blob_offset, blob_length;
354 335 char *security_blob;
355 336  
... ... @@ -377,11 +358,10 @@
377 358  
378 359 req->hdr.SessionId = 0;
379 360  
380   - for (i = 0; i < SMB2_NUM_PROT; i++)
381   - req->Dialects[i] = smb2protocols[i].name;
  361 + req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
382 362  
383   - req->DialectCount = cpu_to_le16(i);
384   - inc_rfc1001_len(req, i * 2);
  363 + req->DialectCount = cpu_to_le16(1); /* One vers= at a time for now */
  364 + inc_rfc1001_len(req, 2);
385 365  
386 366 /* only one of SMB2 signing flags may be set in SMB2 request */
387 367 if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN)
... ... @@ -391,7 +371,7 @@
391 371  
392 372 req->SecurityMode = cpu_to_le16(temp);
393 373  
394   - req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
  374 + req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities);
395 375  
396 376 memcpy(req->ClientGUID, cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
397 377  
398 378  
... ... @@ -411,10 +391,14 @@
411 391  
412 392 cFYI(1, "mode 0x%x", rsp->SecurityMode);
413 393  
414   - if (rsp->DialectRevision == smb2protocols[SMB21_PROT].name)
  394 + /* BB we may eventually want to match the negotiated vs. requested
  395 + dialect, even though we are only requesting one at a time */
  396 + if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
  397 + cFYI(1, "negotiated smb2.0 dialect");
  398 + else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
415 399 cFYI(1, "negotiated smb2.1 dialect");
416   - else if (rsp->DialectRevision == smb2protocols[SMB2_PROT].name)
417   - cFYI(1, "negotiated smb2 dialect");
  400 + else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
  401 + cFYI(1, "negotiated smb3.0 dialect");
418 402 else {
419 403 cERROR(1, "Illegal dialect returned by server %d",
420 404 le16_to_cpu(rsp->DialectRevision));
... ... @@ -163,9 +163,15 @@
163 163 __le32 Capabilities;
164 164 __u8 ClientGUID[SMB2_CLIENT_GUID_SIZE];
165 165 __le64 ClientStartTime; /* MBZ */
166   - __le16 Dialects[2]; /* variable length */
  166 + __le16 Dialects[1]; /* One dialect (vers=) at a time for now */
167 167 } __packed;
168 168  
  169 +/* Dialects */
  170 +#define SMB20_PROT_ID 0x0202
  171 +#define SMB21_PROT_ID 0x0210
  172 +#define SMB30_PROT_ID 0x0300
  173 +#define BAD_PROT_ID 0xFFFF
  174 +
169 175 /* SecurityMode flags */
170 176 #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001
171 177 #define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002
... ... @@ -173,6 +179,10 @@
173 179 #define SMB2_GLOBAL_CAP_DFS 0x00000001
174 180 #define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
175 181 #define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
  182 +#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */
  183 +#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
  184 +#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
  185 +#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
176 186 /* Internal types */
177 187 #define SMB2_NT_FIND 0x00100000
178 188 #define SMB2_LARGE_FILES 0x00200000