diff options
author | Steve French <sfrench@us.ibm.com> | 2006-01-14 00:34:58 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-01-14 00:34:58 -0500 |
commit | eeac8047fcf4c659eb15f2e27a0ef4aeba64157f (patch) | |
tree | 91b1e32bb9f2d6f9e9a122bd5e737df40701ab11 | |
parent | 84153973a29dfb3f3d9fe2fe75c2cd613a3cdf27 (diff) |
[CIFS] Fix CIFS to recognize share mode security
Fix Samba bugzilla bug 3301
In share mode encrypted password must be sent on tree connection (in our
case only the NTLM password is sent, not the older LANMAN one).
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 20 | ||||
-rw-r--r-- | fs/cifs/connect.c | 27 |
4 files changed, 41 insertions, 15 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index c7995c96f069..d335015473a5 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -3,7 +3,8 @@ Version 1.40 | |||
3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance | 3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance |
4 | of readpages by eliminating one extra memcpy. Allow update of file size | 4 | of readpages by eliminating one extra memcpy. Allow update of file size |
5 | from remote server even if file is open for write as long as mount is | 5 | from remote server even if file is open for write as long as mount is |
6 | directio. | 6 | directio. Recognize share mode security and send NTLM encrypted password |
7 | on tree connect if share mode negotiated. | ||
7 | 8 | ||
8 | Version 1.39 | 9 | Version 1.39 |
9 | ------------ | 10 | ------------ |
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index d152ff50ea8c..d0776ac2b804 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -26,13 +26,13 @@ struct cifs_sid { | |||
26 | __u8 revision; /* revision level */ | 26 | __u8 revision; /* revision level */ |
27 | __u8 num_subauths; | 27 | __u8 num_subauths; |
28 | __u8 authority[6]; | 28 | __u8 authority[6]; |
29 | __u8 sub_auth[4]; | 29 | __u32 sub_auth[4]; |
30 | /* next sub_auth if any ... */ | 30 | /* next sub_auth if any ... */ |
31 | } __attribute__((packed)); | 31 | } __attribute__((packed)); |
32 | 32 | ||
33 | /* everyone */ | 33 | /* everyone */ |
34 | const cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | 34 | extern const struct cifs_sid sid_everyone; |
35 | /* group users */ | 35 | /* group users */ |
36 | const cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | 36 | extern const struct cifs_sid sid_user; |
37 | 37 | ||
38 | #endif /* _CIFSACL_H */ | 38 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index ca0f573e9791..7a4e936d726c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "cifsproto.h" | 37 | #include "cifsproto.h" |
38 | #include "cifs_unicode.h" | 38 | #include "cifs_unicode.h" |
39 | #include "cifs_debug.h" | 39 | #include "cifs_debug.h" |
40 | #include "cifsacl.h" | ||
40 | 41 | ||
41 | #ifdef CONFIG_CIFS_POSIX | 42 | #ifdef CONFIG_CIFS_POSIX |
42 | static struct { | 43 | static struct { |
@@ -372,8 +373,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
372 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 373 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
373 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 374 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
374 | if (rc == 0) { | 375 | if (rc == 0) { |
375 | server->secMode = pSMBr->SecurityMode; | 376 | server->secMode = pSMBr->SecurityMode; |
376 | server->secType = NTLM; /* BB override default for | 377 | if((server->secMode & SECMODE_USER) == 0) |
378 | cFYI(1,("share mode security")); | ||
379 | server->secType = NTLM; /* BB override default for | ||
377 | NTLMv2 or kerberos v5 */ | 380 | NTLMv2 or kerberos v5 */ |
378 | /* one byte - no need to convert this or EncryptionKeyLen | 381 | /* one byte - no need to convert this or EncryptionKeyLen |
379 | from little endian */ | 382 | from little endian */ |
@@ -383,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
383 | min(le32_to_cpu(pSMBr->MaxBufferSize), | 386 | min(le32_to_cpu(pSMBr->MaxBufferSize), |
384 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 387 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
385 | server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); | 388 | server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); |
386 | cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); | 389 | cFYI(0, ("Max buf = %d", ses->server->maxBuf)); |
387 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | 390 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); |
388 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 391 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
389 | server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); | 392 | server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); |
@@ -411,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
411 | (server->server_GUID, | 414 | (server->server_GUID, |
412 | pSMBr->u.extended_response. | 415 | pSMBr->u.extended_response. |
413 | GUID, 16) != 0) { | 416 | GUID, 16) != 0) { |
414 | cFYI(1, | 417 | cFYI(1, ("server UID changed")); |
415 | ("UID of server does not match previous connection to same ip address")); | ||
416 | memcpy(server-> | 418 | memcpy(server-> |
417 | server_GUID, | 419 | server_GUID, |
418 | pSMBr->u. | 420 | pSMBr->u. |
@@ -2494,8 +2496,14 @@ GetExtAttrOut: | |||
2494 | 2496 | ||
2495 | #endif /* CONFIG_POSIX */ | 2497 | #endif /* CONFIG_POSIX */ |
2496 | 2498 | ||
2499 | |||
2500 | /* security id for everyone */ | ||
2501 | const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | ||
2502 | /* group users */ | ||
2503 | const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | ||
2504 | |||
2497 | /* Convert CIFS ACL to POSIX form */ | 2505 | /* Convert CIFS ACL to POSIX form */ |
2498 | static int parse_sec_desc(struct sec_desc * psec_desc, int acl_len) | 2506 | static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len) |
2499 | { | 2507 | { |
2500 | return 0; | 2508 | return 0; |
2501 | } | 2509 | } |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1817d5313a8a..88f60aa52058 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1795,7 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1795 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1795 | cifs_sb->mnt_gid = volume_info.linux_gid; |
1796 | cifs_sb->mnt_file_mode = volume_info.file_mode; | 1796 | cifs_sb->mnt_file_mode = volume_info.file_mode; |
1797 | cifs_sb->mnt_dir_mode = volume_info.dir_mode; | 1797 | cifs_sb->mnt_dir_mode = volume_info.dir_mode; |
1798 | cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); | 1798 | cFYI(1,("file mode: 0x%x dir mode: 0x%x", |
1799 | cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); | ||
1799 | 1800 | ||
1800 | if(volume_info.noperm) | 1801 | if(volume_info.noperm) |
1801 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | 1802 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; |
@@ -1972,7 +1973,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1972 | __u32 capabilities; | 1973 | __u32 capabilities; |
1973 | __u16 count; | 1974 | __u16 count; |
1974 | 1975 | ||
1975 | cFYI(1, ("In sesssetup ")); | 1976 | cFYI(1, ("In sesssetup")); |
1976 | if(ses == NULL) | 1977 | if(ses == NULL) |
1977 | return -EINVAL; | 1978 | return -EINVAL; |
1978 | user = ses->userName; | 1979 | user = ses->userName; |
@@ -3248,9 +3249,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3248 | 3249 | ||
3249 | pSMB->AndXCommand = 0xFF; | 3250 | pSMB->AndXCommand = 0xFF; |
3250 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); | 3251 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); |
3251 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | ||
3252 | bcc_ptr = &pSMB->Password[0]; | 3252 | bcc_ptr = &pSMB->Password[0]; |
3253 | bcc_ptr++; /* skip password */ | 3253 | if((ses->server->secMode) & SECMODE_USER) { |
3254 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | ||
3255 | bcc_ptr++; /* skip password */ | ||
3256 | } else { | ||
3257 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); | ||
3258 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | ||
3259 | specified as required (when that support is added to | ||
3260 | the vfs in the future) as only NTLM or the much | ||
3261 | weaker LANMAN (which we do not send) is accepted | ||
3262 | by Samba (not sure whether other servers allow | ||
3263 | NTLMv2 password here) */ | ||
3264 | SMBNTencrypt(ses->password, | ||
3265 | ses->server->cryptKey, | ||
3266 | bcc_ptr); | ||
3267 | |||
3268 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | ||
3269 | *bcc_ptr = 0; | ||
3270 | bcc_ptr++; /* align */ | ||
3271 | } | ||
3254 | 3272 | ||
3255 | if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 3273 | if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
3256 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 3274 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
@@ -3268,7 +3286,6 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3268 | bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ | 3286 | bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ |
3269 | bcc_ptr += 2; /* skip trailing null */ | 3287 | bcc_ptr += 2; /* skip trailing null */ |
3270 | } else { /* ASCII */ | 3288 | } else { /* ASCII */ |
3271 | |||
3272 | strcpy(bcc_ptr, tree); | 3289 | strcpy(bcc_ptr, tree); |
3273 | bcc_ptr += strlen(tree) + 1; | 3290 | bcc_ptr += strlen(tree) + 1; |
3274 | } | 3291 | } |