aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/README5
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/cifssmb.c18
-rw-r--r--fs/cifs/connect.c23
-rw-r--r--fs/cifs/sess.c44
6 files changed, 58 insertions, 36 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 79a202b8f66a..a61d17ed1827 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -7,7 +7,8 @@ so we can do search (ls etc.) to OS/2. Do not send NTCreateX
7or recent levels of FindFirst unless server says it supports NT SMBs 7or recent levels of FindFirst unless server says it supports NT SMBs
8(instead use legacy equivalents from LANMAN dialect). Fix to allow 8(instead use legacy equivalents from LANMAN dialect). Fix to allow
9NTLMv2 authentication support (now can use stronger password hashing 9NTLMv2 authentication support (now can use stronger password hashing
10on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004) 10on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
11Allow override of global cifs security flags on mount via "sec=" option(s).
11 12
12Version 1.43 13Version 1.43
13------------ 14------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 46c2cfa5acf3..7986d0d97ace 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -443,7 +443,10 @@ A partial list of the supported mount options follows:
443 SFU does). In the future the bottom 9 bits of the mode 443 SFU does). In the future the bottom 9 bits of the mode
444 mode also will be emulated using queries of the security 444 mode also will be emulated using queries of the security
445 descriptor (ACL). 445 descriptor (ACL).
446sec Security mode. Allowed values are: 446 sign Must use packet signing (helps avoid unwanted data modification
447 by intermediate systems in the route). Note that signing
448 does not work with lanman or plaintext authentication.
449 sec Security mode. Allowed values are:
447 none attempt to connection as a null user (no name) 450 none attempt to connection as a null user (no name)
448 krb5 Use Kerberos version 5 authentication 451 krb5 Use Kerberos version 5 authentication
449 krb5i Use Kerberos authentication and packet signing 452 krb5i Use Kerberos authentication and packet signing
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 87453a6bcaf8..6d7cf5f3bc0b 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -186,6 +186,7 @@ struct cifsSesInfo {
186 struct TCP_Server_Info *server; /* pointer to server info */ 186 struct TCP_Server_Info *server; /* pointer to server info */
187 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 187 atomic_t inUse; /* # of mounts (tree connections) on this ses */
188 enum statusEnum status; 188 enum statusEnum status;
189 unsigned overrideSecFlg; /* if non-zero override global sec flags */
189 __u16 ipc_tid; /* special tid for connection to IPC share */ 190 __u16 ipc_tid; /* special tid for connection to IPC share */
190 __u16 flags; 191 __u16 flags;
191 char *serverOS; /* name of operating system underlying server */ 192 char *serverOS; /* name of operating system underlying server */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 38f83db20764..de405bfb67d2 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -396,6 +396,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
396 int i; 396 int i;
397 struct TCP_Server_Info * server; 397 struct TCP_Server_Info * server;
398 u16 count; 398 u16 count;
399 unsigned int secFlags;
399 400
400 if(ses->server) 401 if(ses->server)
401 server = ses->server; 402 server = ses->server;
@@ -407,9 +408,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
407 (void **) &pSMB, (void **) &pSMBr); 408 (void **) &pSMB, (void **) &pSMBr);
408 if (rc) 409 if (rc)
409 return rc; 410 return rc;
411
412 /* if any of auth flags (ie not sign or seal) are overriden use them */
413 if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
414 secFlags = ses->overrideSecFlg;
415 else /* if override flags set only sign/seal OR them with global auth */
416 secFlags = extended_security | ses->overrideSecFlg;
417
410 pSMB->hdr.Mid = GetNextMid(server); 418 pSMB->hdr.Mid = GetNextMid(server);
411 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 419 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
412 if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) 420 if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
413 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 421 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
414 422
415 count = 0; 423 count = 0;
@@ -439,8 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
439 && (pSMBr->DialectIndex == LANMAN_PROT)) { 447 && (pSMBr->DialectIndex == LANMAN_PROT)) {
440 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; 448 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
441 449
442 if((extended_security & CIFSSEC_MAY_LANMAN) || 450 if((secFlags & CIFSSEC_MAY_LANMAN) ||
443 (extended_security & CIFSSEC_MAY_PLNTXT)) 451 (secFlags & CIFSSEC_MAY_PLNTXT))
444 server->secType = LANMAN; 452 server->secType = LANMAN;
445 else { 453 else {
446 cERROR(1, ("mount failed weak security disabled" 454 cERROR(1, ("mount failed weak security disabled"
@@ -498,12 +506,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
498 506
499 if((server->secMode & SECMODE_PW_ENCRYPT) == 0) 507 if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
500#ifdef CONFIG_CIFS_WEAK_PW_HASH 508#ifdef CONFIG_CIFS_WEAK_PW_HASH
501 if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0) 509 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
502#endif /* CIFS_WEAK_PW_HASH */ 510#endif /* CIFS_WEAK_PW_HASH */
503 cERROR(1,("Server requests plain text password" 511 cERROR(1,("Server requests plain text password"
504 " but client support disabled")); 512 " but client support disabled"));
505 513
506 if(extended_security & CIFSSEC_MUST_NTLMV2) 514 if(secFlags & CIFSSEC_MUST_NTLMV2)
507 server->secType = NTLMv2; 515 server->secType = NTLMv2;
508 else 516 else
509 server->secType = NTLM; 517 server->secType = NTLM;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c0f98ddea88c..876eb9ef85fe 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -915,32 +915,32 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
915 cERROR(1,("no security value specified")); 915 cERROR(1,("no security value specified"));
916 continue; 916 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) { 917 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->secFlg = CIFSSEC_MAY_KRB5 | 918 vol->secFlg |= CIFSSEC_MAY_KRB5 |
919 CIFSSEC_MUST_SIGN; 919 CIFSSEC_MUST_SIGN;
920 } else if (strnicmp(value, "krb5p", 5) == 0) { 920 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->secFlg = CIFSSEC_MUST_SEAL | 921 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
922 CIFSSEC_MAY_KRB5; */ 922 CIFSSEC_MAY_KRB5; */
923 cERROR(1,("Krb5 cifs privacy not supported")); 923 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1; 924 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) { 925 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->secFlg = CIFSSEC_MAY_KRB5; 926 vol->secFlg |= CIFSSEC_MAY_KRB5;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->secFlg = CIFSSEC_MAY_NTLMV2 | 928 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
929 CIFSSEC_MUST_SIGN; 929 CIFSSEC_MUST_SIGN;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) { 930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->secFlg = CIFSSEC_MAY_NTLMV2; 931 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) { 932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->secFlg = CIFSSEC_MAY_NTLM | 933 vol->secFlg |= CIFSSEC_MAY_NTLM |
934 CIFSSEC_MUST_SIGN; 934 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlm", 4) == 0) { 935 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */ 936 /* ntlm is default so can be turned off too */
937 vol->secFlg = CIFSSEC_MAY_NTLM; 937 vol->secFlg |= CIFSSEC_MAY_NTLM;
938 } else if (strnicmp(value, "nontlm", 6) == 0) { 938 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 /* BB is there a better way to do this? */ 939 /* BB is there a better way to do this? */
940 vol->secFlg = CIFSSEC_MAY_NTLMV2; 940 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
941#ifdef CONFIG_CIFS_WEAK_PW_HASH 941#ifdef CONFIG_CIFS_WEAK_PW_HASH
942 } else if (strnicmp(value, "lanman", 6) == 0) { 942 } else if (strnicmp(value, "lanman", 6) == 0) {
943 vol->secFlg = CIFSSEC_MAY_LANMAN; 943 vol->secFlg |= CIFSSEC_MAY_LANMAN;
944#endif 944#endif
945 } else if (strnicmp(value, "none", 4) == 0) { 945 } else if (strnicmp(value, "none", 4) == 0) {
946 vol->nullauth = 1; 946 vol->nullauth = 1;
@@ -1173,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1173 vol->no_psx_acl = 0; 1173 vol->no_psx_acl = 0;
1174 } else if (strnicmp(data, "noacl",5) == 0) { 1174 } else if (strnicmp(data, "noacl",5) == 0) {
1175 vol->no_psx_acl = 1; 1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "sign",4) == 0) {
1177 vol->secFlg |= CIFSSEC_MUST_SIGN;
1178/* } else if (strnicmp(data, "seal",4) == 0) {
1179 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1176 } else if (strnicmp(data, "direct",6) == 0) { 1180 } else if (strnicmp(data, "direct",6) == 0) {
1177 vol->direct_io = 1; 1181 vol->direct_io = 1;
1178 } else if (strnicmp(data, "forcedirectio",13) == 0) { 1182 } else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1776,6 +1780,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1776 volume_info.domainname); 1780 volume_info.domainname);
1777 } 1781 }
1778 pSesInfo->linux_uid = volume_info.linux_uid; 1782 pSesInfo->linux_uid = volume_info.linux_uid;
1783 pSesInfo->overrideSecFlg = volume_info.secFlg;
1779 down(&pSesInfo->sesSem); 1784 down(&pSesInfo->sesSem);
1780 /* BB FIXME need to pass vol->secFlgs BB */ 1785 /* BB FIXME need to pass vol->secFlgs BB */
1781 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1786 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 70e32a81c213..7737edd1baf1 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -138,7 +138,7 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
138 strncpy(bcc_ptr, ses->userName, 300); 138 strncpy(bcc_ptr, ses->userName, 300);
139 } 139 }
140 /* BB improve check for overflow */ 140 /* BB improve check for overflow */
141 bcc_ptr += strnlen(ses->userName, 200); 141 bcc_ptr += strnlen(ses->userName, 300);
142 *bcc_ptr = 0; 142 *bcc_ptr = 0;
143 bcc_ptr++; /* account for null termination */ 143 bcc_ptr++; /* account for null termination */
144 144
@@ -313,11 +313,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
313 int wct; 313 int wct;
314 struct smb_hdr *smb_buf; 314 struct smb_hdr *smb_buf;
315 char *bcc_ptr; 315 char *bcc_ptr;
316 char *str_area;
316 SESSION_SETUP_ANDX *pSMB; 317 SESSION_SETUP_ANDX *pSMB;
317 __u32 capabilities; 318 __u32 capabilities;
318 int count; 319 int count;
319 int resp_buf_type = 0; 320 int resp_buf_type = 0;
320 struct kvec iov[2]; /* BB split variable length info into 2nd iovec */ 321 struct kvec iov[2];
321 enum securityEnum type; 322 enum securityEnum type;
322 __u16 action; 323 __u16 action;
323 int bytes_remaining; 324 int bytes_remaining;
@@ -351,7 +352,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
351 pSMB = (SESSION_SETUP_ANDX *)smb_buf; 352 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
352 353
353 capabilities = cifs_ssetup_hdr(ses, pSMB); 354 capabilities = cifs_ssetup_hdr(ses, pSMB);
354 bcc_ptr = pByteArea(smb_buf); 355
356 /* we will send the SMB in two pieces,
357 a fixed length beginning part, and a
358 second part which will include the strings
359 and rest of bcc area, in order to avoid having
360 to do a large buffer 17K allocation */
361 iov[0].iov_base = (char *)pSMB;
362 iov[0].iov_len = smb_buf->smb_buf_length + 4;
363
364 /* 2000 big enough to fit max user, domain, NOS name etc. */
365 str_area = kmalloc(2000, GFP_KERNEL);
366 bcc_ptr = str_area;
355 367
356 if(type == LANMAN) { 368 if(type == LANMAN) {
357#ifdef CONFIG_CIFS_WEAK_PW_HASH 369#ifdef CONFIG_CIFS_WEAK_PW_HASH
@@ -365,10 +377,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
365 377
366 calc_lanman_hash(ses, lnm_session_key); 378 calc_lanman_hash(ses, lnm_session_key);
367 379
368#ifdef CONFIG_CIFS_DEBUG2 380/* #ifdef CONFIG_CIFS_DEBUG2
369 cifs_dump_mem("cryptkey: ",ses->server->cryptKey, 381 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
370 CIFS_SESS_KEY_SIZE); 382 CIFS_SESS_KEY_SIZE);
371#endif 383#endif */
372 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); 384 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
373 bcc_ptr += CIFS_SESS_KEY_SIZE; 385 bcc_ptr += CIFS_SESS_KEY_SIZE;
374 386
@@ -377,7 +389,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
377 changed to do higher than lanman dialect and 389 changed to do higher than lanman dialect and
378 we reconnected would we ever calc signing_key? */ 390 we reconnected would we ever calc signing_key? */
379 391
380 cERROR(1,("Negotiating LANMAN setting up strings")); 392 cFYI(1,("Negotiating LANMAN setting up strings"));
381 /* Unicode not allowed for LANMAN dialects */ 393 /* Unicode not allowed for LANMAN dialects */
382 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); 394 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
383#endif 395#endif
@@ -396,7 +408,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
396 408
397 if(first_time) /* should this be moved into common code 409 if(first_time) /* should this be moved into common code
398 with similar ntlmv2 path? */ 410 with similar ntlmv2 path? */
399 cifs_calculate_mac_key( ses->server->mac_signing_key, 411 cifs_calculate_mac_key(ses->server->mac_signing_key,
400 ntlm_session_key, ses->password); 412 ntlm_session_key, ses->password);
401 /* copy session key */ 413 /* copy session key */
402 414
@@ -454,23 +466,14 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
454 /* BB set password lengths */ 466 /* BB set password lengths */
455 } 467 }
456 468
457 count = (long) bcc_ptr - (long) pByteArea(smb_buf); 469 count = (long) bcc_ptr - (long) str_area;
458 smb_buf->smb_buf_length += count; 470 smb_buf->smb_buf_length += count;
459 471
460 /* if we switch to small buffers, count will need to be fewer
461 than 383 (strings less than 335 bytes) */
462
463 BCC_LE(smb_buf) = cpu_to_le16(count); 472 BCC_LE(smb_buf) = cpu_to_le16(count);
464 473
465 474 iov[1].iov_base = str_area;
466 /* BB FIXME check for other non ntlm code paths */ 475 iov[1].iov_len = count;
467 476 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
468 /* BB check is this too big for a small smb? */
469
470 iov[0].iov_base = (char *)pSMB;
471 iov[0].iov_len = smb_buf->smb_buf_length + 4;
472
473 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
474 /* SMB request buf freed in SendReceive2 */ 477 /* SMB request buf freed in SendReceive2 */
475 478
476 cFYI(1,("ssetup rc from sendrecv2 is %d",rc)); 479 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
@@ -515,6 +518,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
515 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp); 518 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
516 519
517ssetup_exit: 520ssetup_exit:
521 kfree(str_area);
518 if(resp_buf_type == CIFS_SMALL_BUFFER) { 522 if(resp_buf_type == CIFS_SMALL_BUFFER) {
519 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base)); 523 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
520 cifs_small_buf_release(iov[0].iov_base); 524 cifs_small_buf_release(iov[0].iov_base);