aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/README44
-rw-r--r--fs/cifs/asn1.c11
-rw-r--r--fs/cifs/cifs_spnego.c4
-rw-r--r--fs/cifs/cifs_spnego.h2
-rw-r--r--fs/cifs/cifsencrypt.c1
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/connect.c33
-rw-r--r--fs/cifs/dns_resolve.c7
-rw-r--r--fs/cifs/file.c4
-rw-r--r--fs/cifs/inode.c3
-rw-r--r--fs/cifs/sess.c13
12 files changed, 104 insertions, 31 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index f5d0083e09fa..06e521a945c3 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -4,7 +4,15 @@ Fix premature write failure on congested networks (we would give up
4on EAGAIN from the socket too quickly on large writes). 4on EAGAIN from the socket too quickly on large writes).
5Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. 5Cifs_mkdir and cifs_create now respect the setgid bit on parent dir.
6Fix endian problems in acl (mode from/to cifs acl) on bigendian 6Fix endian problems in acl (mode from/to cifs acl) on bigendian
7architectures. 7architectures. Fix problems with preserving timestamps on copying open
8files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit
9on parent directory when server supports Unix Extensions but not POSIX
10create. Update cifs.upcall version to handle new Kerberos sec flags
11(this requires update of cifs.upcall program from Samba). Fix memory leak
12on dns_upcall (resolving DFS referralls). Fix plain text password
13authentication (requires setting SecurityFlags to 0x30030 to enable
14lanman and plain text though). Fix writes to be at correct offset when
15file is open with O_APPEND and file is on a directio (forcediretio) mount.
8 16
9Version 1.53 17Version 1.53
10------------ 18------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 2bd6fe556f88..bd2343d4c6a6 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -542,10 +542,20 @@ SecurityFlags Flags which control security negotiation and
542 hashing mechanisms (as "must use") on the other hand 542 hashing mechanisms (as "must use") on the other hand
543 does not make much sense. Default flags are 543 does not make much sense. Default flags are
544 0x07007 544 0x07007
545 (NTLM, NTLMv2 and packet signing allowed). Maximum 545 (NTLM, NTLMv2 and packet signing allowed). The maximum
546 allowable flags if you want to allow mounts to servers 546 allowable flags if you want to allow mounts to servers
547 using weaker password hashes is 0x37037 (lanman, 547 using weaker password hashes is 0x37037 (lanman,
548 plaintext, ntlm, ntlmv2, signing allowed): 548 plaintext, ntlm, ntlmv2, signing allowed). Some
549 SecurityFlags require the corresponding menuconfig
550 options to be enabled (lanman and plaintext require
551 CONFIG_CIFS_WEAK_PW_HASH for example). Enabling
552 plaintext authentication currently requires also
553 enabling lanman authentication in the security flags
554 because the cifs module only supports sending
555 laintext passwords using the older lanman dialect
556 form of the session setup SMB. (e.g. for authentication
557 using plain text passwords, set the SecurityFlags
558 to 0x30030):
549 559
550 may use packet signing 0x00001 560 may use packet signing 0x00001
551 must use packet signing 0x01001 561 must use packet signing 0x01001
@@ -642,8 +652,30 @@ The statistics for the number of total SMBs and oplock breaks are different in
642that they represent all for that share, not just those for which the server 652that they represent all for that share, not just those for which the server
643returned success. 653returned success.
644 654
645Also note that "cat /proc/fs/cifs/DebugData" will display information about 655Also note that "cat /proc/fs/cifs/DebugData" will display information about
646the active sessions and the shares that are mounted. 656the active sessions and the shares that are mounted.
647Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is 657
648on but requires a user space helper (from the Samba project). NTLM and NTLMv2 and 658Enabling Kerberos (extended security) works but requires version 1.2 or later
649LANMAN support do not require this helper. 659of the helper program cifs.upcall to be present and to be configured in the
660/etc/request-key.conf file. The cifs.upcall helper program is from the Samba
661project(http://www.samba.org). NTLM and NTLMv2 and LANMAN support do not
662require this helper. Note that NTLMv2 security (which does not require the
663cifs.upcall helper program), instead of using Kerberos, is sufficient for
664some use cases.
665
666Enabling DFS support (used to access shares transparently in an MS-DFS
667global name space) requires that CONFIG_CIFS_EXPERIMENTAL be enabled. In
668addition, DFS support for target shares which are specified as UNC
669names which begin with host names (rather than IP addresses) requires
670a user space helper (such as cifs.upcall) to be present in order to
671translate host names to ip address, and the user space helper must also
672be configured in the file /etc/request-key.conf
673
674To use cifs Kerberos and DFS support, the Linux keyutils package should be
675installed and something like the following lines should be added to the
676/etc/request-key.conf file:
677
678create cifs.spnego * * /usr/local/sbin/cifs.upcall %k
679create dns_resolver * * /usr/local/sbin/cifs.upcall %k
680
681
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 5fabd2caf93c..1b09f1670061 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -476,6 +476,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
476 unsigned int cls, con, tag, oidlen, rc; 476 unsigned int cls, con, tag, oidlen, rc;
477 bool use_ntlmssp = false; 477 bool use_ntlmssp = false;
478 bool use_kerberos = false; 478 bool use_kerberos = false;
479 bool use_mskerberos = false;
479 480
480 *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ 481 *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
481 482
@@ -574,10 +575,12 @@ decode_negTokenInit(unsigned char *security_blob, int length,
574 *(oid + 1), *(oid + 2), *(oid + 3))); 575 *(oid + 1), *(oid + 2), *(oid + 3)));
575 576
576 if (compare_oid(oid, oidlen, MSKRB5_OID, 577 if (compare_oid(oid, oidlen, MSKRB5_OID,
577 MSKRB5_OID_LEN)) 578 MSKRB5_OID_LEN) &&
578 use_kerberos = true; 579 !use_kerberos)
580 use_mskerberos = true;
579 else if (compare_oid(oid, oidlen, KRB5_OID, 581 else if (compare_oid(oid, oidlen, KRB5_OID,
580 KRB5_OID_LEN)) 582 KRB5_OID_LEN) &&
583 !use_mskerberos)
581 use_kerberos = true; 584 use_kerberos = true;
582 else if (compare_oid(oid, oidlen, NTLMSSP_OID, 585 else if (compare_oid(oid, oidlen, NTLMSSP_OID,
583 NTLMSSP_OID_LEN)) 586 NTLMSSP_OID_LEN))
@@ -630,6 +633,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
630 633
631 if (use_kerberos) 634 if (use_kerberos)
632 *secType = Kerberos; 635 *secType = Kerberos;
636 else if (use_mskerberos)
637 *secType = MSKerberos;
633 else if (use_ntlmssp) 638 else if (use_ntlmssp)
634 *secType = NTLMSSP; 639 *secType = NTLMSSP;
635 640
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 2434ab0e8791..117ef4bba68e 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -114,9 +114,11 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
114 114
115 dp = description + strlen(description); 115 dp = description + strlen(description);
116 116
117 /* for now, only sec=krb5 is valid */ 117 /* for now, only sec=krb5 and sec=mskrb5 are valid */
118 if (server->secType == Kerberos) 118 if (server->secType == Kerberos)
119 sprintf(dp, ";sec=krb5"); 119 sprintf(dp, ";sec=krb5");
120 else if (server->secType == MSKerberos)
121 sprintf(dp, ";sec=mskrb5");
120 else 122 else
121 goto out; 123 goto out;
122 124
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h
index 05a34b17a1ab..e4041ec4d712 100644
--- a/fs/cifs/cifs_spnego.h
+++ b/fs/cifs/cifs_spnego.h
@@ -23,7 +23,7 @@
23#ifndef _CIFS_SPNEGO_H 23#ifndef _CIFS_SPNEGO_H
24#define _CIFS_SPNEGO_H 24#define _CIFS_SPNEGO_H
25 25
26#define CIFS_SPNEGO_UPCALL_VERSION 1 26#define CIFS_SPNEGO_UPCALL_VERSION 2
27 27
28/* 28/*
29 * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. 29 * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 83fd40dc1ef0..bd5f13d38450 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -294,6 +294,7 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
294 294
295 if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) 295 if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
296 if (extended_security & CIFSSEC_MAY_PLNTXT) { 296 if (extended_security & CIFSSEC_MAY_PLNTXT) {
297 memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE);
297 memcpy(lnm_session_key, password_with_pad, 298 memcpy(lnm_session_key, password_with_pad,
298 CIFS_ENCPWD_SIZE); 299 CIFS_ENCPWD_SIZE);
299 return; 300 return;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7e1cf262effe..8dfd6f24d488 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -80,7 +80,8 @@ enum securityEnum {
80 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 80 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
81 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 81 RawNTLMSSP, /* NTLMSSP without SPNEGO */
82 NTLMSSP, /* NTLMSSP via SPNEGO */ 82 NTLMSSP, /* NTLMSSP via SPNEGO */
83 Kerberos /* Kerberos via SPNEGO */ 83 Kerberos, /* Kerberos via SPNEGO */
84 MSKerberos, /* MS Kerberos via SPNEGO */
84}; 85};
85 86
86enum protocolEnum { 87enum protocolEnum {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0711db65afe8..4c13bcdb92a5 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3598,19 +3598,21 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3598 char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 3598 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3599 bool ntlmv2_flag = false; 3599 bool ntlmv2_flag = false;
3600 int first_time = 0; 3600 int first_time = 0;
3601 struct TCP_Server_Info *server = pSesInfo->server;
3601 3602
3602 /* what if server changes its buffer size after dropping the session? */ 3603 /* what if server changes its buffer size after dropping the session? */
3603 if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { 3604 if (server->maxBuf == 0) /* no need to send on reconnect */ {
3604 rc = CIFSSMBNegotiate(xid, pSesInfo); 3605 rc = CIFSSMBNegotiate(xid, pSesInfo);
3605 if (rc == -EAGAIN) /* retry only once on 1st time connection */ { 3606 if (rc == -EAGAIN) {
3607 /* retry only once on 1st time connection */
3606 rc = CIFSSMBNegotiate(xid, pSesInfo); 3608 rc = CIFSSMBNegotiate(xid, pSesInfo);
3607 if (rc == -EAGAIN) 3609 if (rc == -EAGAIN)
3608 rc = -EHOSTDOWN; 3610 rc = -EHOSTDOWN;
3609 } 3611 }
3610 if (rc == 0) { 3612 if (rc == 0) {
3611 spin_lock(&GlobalMid_Lock); 3613 spin_lock(&GlobalMid_Lock);
3612 if (pSesInfo->server->tcpStatus != CifsExiting) 3614 if (server->tcpStatus != CifsExiting)
3613 pSesInfo->server->tcpStatus = CifsGood; 3615 server->tcpStatus = CifsGood;
3614 else 3616 else
3615 rc = -EHOSTDOWN; 3617 rc = -EHOSTDOWN;
3616 spin_unlock(&GlobalMid_Lock); 3618 spin_unlock(&GlobalMid_Lock);
@@ -3623,23 +3625,22 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3623 goto ss_err_exit; 3625 goto ss_err_exit;
3624 3626
3625 pSesInfo->flags = 0; 3627 pSesInfo->flags = 0;
3626 pSesInfo->capabilities = pSesInfo->server->capabilities; 3628 pSesInfo->capabilities = server->capabilities;
3627 if (linuxExtEnabled == 0) 3629 if (linuxExtEnabled == 0)
3628 pSesInfo->capabilities &= (~CAP_UNIX); 3630 pSesInfo->capabilities &= (~CAP_UNIX);
3629 /* pSesInfo->sequence_number = 0;*/ 3631 /* pSesInfo->sequence_number = 0;*/
3630 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 3632 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3631 pSesInfo->server->secMode, 3633 server->secMode, server->capabilities, server->timeAdj));
3632 pSesInfo->server->capabilities, 3634
3633 pSesInfo->server->timeAdj));
3634 if (experimEnabled < 2) 3635 if (experimEnabled < 2)
3635 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); 3636 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3636 else if (extended_security 3637 else if (extended_security
3637 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3638 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3638 && (pSesInfo->server->secType == NTLMSSP)) { 3639 && (server->secType == NTLMSSP)) {
3639 rc = -EOPNOTSUPP; 3640 rc = -EOPNOTSUPP;
3640 } else if (extended_security 3641 } else if (extended_security
3641 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3642 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3642 && (pSesInfo->server->secType == RawNTLMSSP)) { 3643 && (server->secType == RawNTLMSSP)) {
3643 cFYI(1, ("NTLMSSP sesssetup")); 3644 cFYI(1, ("NTLMSSP sesssetup"));
3644 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, 3645 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3645 nls_info); 3646 nls_info);
@@ -3668,12 +3669,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3668 3669
3669 } else { 3670 } else {
3670 SMBNTencrypt(pSesInfo->password, 3671 SMBNTencrypt(pSesInfo->password,
3671 pSesInfo->server->cryptKey, 3672 server->cryptKey,
3672 ntlm_session_key); 3673 ntlm_session_key);
3673 3674
3674 if (first_time) 3675 if (first_time)
3675 cifs_calculate_mac_key( 3676 cifs_calculate_mac_key(
3676 &pSesInfo->server->mac_signing_key, 3677 &server->mac_signing_key,
3677 ntlm_session_key, 3678 ntlm_session_key,
3678 pSesInfo->password); 3679 pSesInfo->password);
3679 } 3680 }
@@ -3686,13 +3687,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3686 nls_info); 3687 nls_info);
3687 } 3688 }
3688 } else { /* old style NTLM 0.12 session setup */ 3689 } else { /* old style NTLM 0.12 session setup */
3689 SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, 3690 SMBNTencrypt(pSesInfo->password, server->cryptKey,
3690 ntlm_session_key); 3691 ntlm_session_key);
3691 3692
3692 if (first_time) 3693 if (first_time)
3693 cifs_calculate_mac_key( 3694 cifs_calculate_mac_key(&server->mac_signing_key,
3694 &pSesInfo->server->mac_signing_key, 3695 ntlm_session_key,
3695 ntlm_session_key, pSesInfo->password); 3696 pSesInfo->password);
3696 3697
3697 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); 3698 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3698 } 3699 }
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index f730ef35499e..a2e0673e1b08 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -47,11 +47,18 @@ static int dns_resolver_instantiate(struct key *key, const void *data,
47 return rc; 47 return rc;
48} 48}
49 49
50static void
51dns_resolver_destroy(struct key *key)
52{
53 kfree(key->payload.data);
54}
55
50struct key_type key_type_dns_resolver = { 56struct key_type key_type_dns_resolver = {
51 .name = "dns_resolver", 57 .name = "dns_resolver",
52 .def_datalen = sizeof(struct in_addr), 58 .def_datalen = sizeof(struct in_addr),
53 .describe = user_describe, 59 .describe = user_describe,
54 .instantiate = dns_resolver_instantiate, 60 .instantiate = dns_resolver_instantiate,
61 .destroy = dns_resolver_destroy,
55 .match = user_match, 62 .match = user_match,
56}; 63};
57 64
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index ff14d14903a0..cbefe1f1f9fe 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -833,6 +833,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
833 return -EBADF; 833 return -EBADF;
834 open_file = (struct cifsFileInfo *) file->private_data; 834 open_file = (struct cifsFileInfo *) file->private_data;
835 835
836 rc = generic_write_checks(file, poffset, &write_size, 0);
837 if (rc)
838 return rc;
839
836 xid = GetXid(); 840 xid = GetXid();
837 841
838 if (*poffset > file->f_path.dentry->d_inode->i_size) 842 if (*poffset > file->f_path.dentry->d_inode->i_size)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 848286861c31..9c548f110102 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -546,7 +546,8 @@ int cifs_get_inode_info(struct inode **pinode,
546 if ((inode->i_mode & S_IWUGO) == 0 && 546 if ((inode->i_mode & S_IWUGO) == 0 &&
547 (attr & ATTR_READONLY) == 0) 547 (attr & ATTR_READONLY) == 0)
548 inode->i_mode |= (S_IWUGO & default_mode); 548 inode->i_mode |= (S_IWUGO & default_mode);
549 inode->i_mode &= ~S_IFMT; 549
550 inode->i_mode &= ~S_IFMT;
550 } 551 }
551 /* clear write bits if ATTR_READONLY is set */ 552 /* clear write bits if ATTR_READONLY is set */
552 if (attr & ATTR_READONLY) 553 if (attr & ATTR_READONLY)
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index ed150efbe27c..252fdc0567f1 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -409,6 +409,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
409#ifdef CONFIG_CIFS_WEAK_PW_HASH 409#ifdef CONFIG_CIFS_WEAK_PW_HASH
410 char lnm_session_key[CIFS_SESS_KEY_SIZE]; 410 char lnm_session_key[CIFS_SESS_KEY_SIZE];
411 411
412 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
413
412 /* no capabilities flags in old lanman negotiation */ 414 /* no capabilities flags in old lanman negotiation */
413 415
414 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); 416 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
@@ -505,7 +507,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
505 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); 507 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
506 } else 508 } else
507 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); 509 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
508 } else if (type == Kerberos) { 510 } else if (type == Kerberos || type == MSKerberos) {
509#ifdef CONFIG_CIFS_UPCALL 511#ifdef CONFIG_CIFS_UPCALL
510 struct cifs_spnego_msg *msg; 512 struct cifs_spnego_msg *msg;
511 spnego_key = cifs_get_spnego_key(ses); 513 spnego_key = cifs_get_spnego_key(ses);
@@ -516,6 +518,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
516 } 518 }
517 519
518 msg = spnego_key->payload.data; 520 msg = spnego_key->payload.data;
521 /* check version field to make sure that cifs.upcall is
522 sending us a response in an expected form */
523 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
524 cERROR(1, ("incorrect version of cifs.upcall (expected"
525 " %d but got %d)",
526 CIFS_SPNEGO_UPCALL_VERSION, msg->version));
527 rc = -EKEYREJECTED;
528 goto ssetup_exit;
529 }
519 /* bail out if key is too long */ 530 /* bail out if key is too long */
520 if (msg->sesskey_len > 531 if (msg->sesskey_len >
521 sizeof(ses->server->mac_signing_key.data.krb5)) { 532 sizeof(ses->server->mac_signing_key.data.krb5)) {