Commit b22dfb73 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] check version in spnego upcall response
  [CIFS] Kerberos support not considered experimental anymore
  [CIFS] distinguish between Kerberos and MSKerberos in upcall
  cifs: add local server pointer to cifs_setup_session
  [CIFS] reindent misindented statement
parents bd5a54e9 3dae49ab
...@@ -1984,7 +1984,6 @@ config CIFS_EXPERIMENTAL ...@@ -1984,7 +1984,6 @@ config CIFS_EXPERIMENTAL
config CIFS_UPCALL config CIFS_UPCALL
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
depends on CIFS_EXPERIMENTAL
depends on KEYS depends on KEYS
help help
Enables an upcall mechanism for CIFS which accesses Enables an upcall mechanism for CIFS which accesses
......
...@@ -4,7 +4,11 @@ Fix premature write failure on congested networks (we would give up ...@@ -4,7 +4,11 @@ Fix premature write failure on congested networks (we would give up
on EAGAIN from the socket too quickly on large writes). on EAGAIN from the socket too quickly on large writes).
Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. Cifs_mkdir and cifs_create now respect the setgid bit on parent dir.
Fix endian problems in acl (mode from/to cifs acl) on bigendian Fix endian problems in acl (mode from/to cifs acl) on bigendian
architectures. architectures. Fix problems with preserving timestamps on copying open
files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit
on parent directory when server supports Unix Extensions but not POSIX
create. Update cifs.upcall version to handle new Kerberos sec flags
(this requires update of cifs.upcall program from Samba).
Version 1.53 Version 1.53
------------ ------------
......
...@@ -642,8 +642,30 @@ The statistics for the number of total SMBs and oplock breaks are different in ...@@ -642,8 +642,30 @@ The statistics for the number of total SMBs and oplock breaks are different in
that they represent all for that share, not just those for which the server that they represent all for that share, not just those for which the server
returned success. returned success.
Also note that "cat /proc/fs/cifs/DebugData" will display information about Also note that "cat /proc/fs/cifs/DebugData" will display information about
the active sessions and the shares that are mounted. the active sessions and the shares that are mounted.
Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is
on but requires a user space helper (from the Samba project). NTLM and NTLMv2 and Enabling Kerberos (extended security) works but requires version 1.2 or later
LANMAN support do not require this helper. of the helper program cifs.upcall to be present and to be configured in the
/etc/request-key.conf file. The cifs.upcall helper program is from the Samba
project(http://www.samba.org). NTLM and NTLMv2 and LANMAN support do not
require this helper. Note that NTLMv2 security (which does not require the
cifs.upcall helper program), instead of using Kerberos, is sufficient for
some use cases.
Enabling DFS support (used to access shares transparently in an MS-DFS
global name space) requires that CONFIG_CIFS_EXPERIMENTAL be enabled. In
addition, DFS support for target shares which are specified as UNC
names which begin with host names (rather than IP addresses) requires
a user space helper (such as cifs.upcall) to be present in order to
translate host names to ip address, and the user space helper must also
be configured in the file /etc/request-key.conf
To use cifs Kerberos and DFS support, the Linux keyutils package should be
installed and something like the following lines should be added to the
/etc/request-key.conf file:
create cifs.spnego * * /usr/local/sbin/cifs.upcall %k
create dns_resolver * * /usr/local/sbin/cifs.upcall %k
...@@ -476,6 +476,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -476,6 +476,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned int cls, con, tag, oidlen, rc; unsigned int cls, con, tag, oidlen, rc;
bool use_ntlmssp = false; bool use_ntlmssp = false;
bool use_kerberos = false; bool use_kerberos = false;
bool use_mskerberos = false;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
...@@ -574,10 +575,12 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -574,10 +575,12 @@ decode_negTokenInit(unsigned char *security_blob, int length,
*(oid + 1), *(oid + 2), *(oid + 3))); *(oid + 1), *(oid + 2), *(oid + 3)));
if (compare_oid(oid, oidlen, MSKRB5_OID, if (compare_oid(oid, oidlen, MSKRB5_OID,
MSKRB5_OID_LEN)) MSKRB5_OID_LEN) &&
use_kerberos = true; !use_kerberos)
use_mskerberos = true;
else if (compare_oid(oid, oidlen, KRB5_OID, else if (compare_oid(oid, oidlen, KRB5_OID,
KRB5_OID_LEN)) KRB5_OID_LEN) &&
!use_mskerberos)
use_kerberos = true; use_kerberos = true;
else if (compare_oid(oid, oidlen, NTLMSSP_OID, else if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN)) NTLMSSP_OID_LEN))
...@@ -630,6 +633,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -630,6 +633,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (use_kerberos) if (use_kerberos)
*secType = Kerberos; *secType = Kerberos;
else if (use_mskerberos)
*secType = MSKerberos;
else if (use_ntlmssp) else if (use_ntlmssp)
*secType = NTLMSSP; *secType = NTLMSSP;
......
...@@ -114,9 +114,11 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) ...@@ -114,9 +114,11 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
dp = description + strlen(description); dp = description + strlen(description);
/* for now, only sec=krb5 is valid */ /* for now, only sec=krb5 and sec=mskrb5 are valid */
if (server->secType == Kerberos) if (server->secType == Kerberos)
sprintf(dp, ";sec=krb5"); sprintf(dp, ";sec=krb5");
else if (server->secType == MSKerberos)
sprintf(dp, ";sec=mskrb5");
else else
goto out; goto out;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#ifndef _CIFS_SPNEGO_H #ifndef _CIFS_SPNEGO_H
#define _CIFS_SPNEGO_H #define _CIFS_SPNEGO_H
#define CIFS_SPNEGO_UPCALL_VERSION 1 #define CIFS_SPNEGO_UPCALL_VERSION 2
/* /*
* The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
......
...@@ -80,7 +80,8 @@ enum securityEnum { ...@@ -80,7 +80,8 @@ enum securityEnum {
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO */ RawNTLMSSP, /* NTLMSSP without SPNEGO */
NTLMSSP, /* NTLMSSP via SPNEGO */ NTLMSSP, /* NTLMSSP via SPNEGO */
Kerberos /* Kerberos via SPNEGO */ Kerberos, /* Kerberos via SPNEGO */
MSKerberos, /* MS Kerberos via SPNEGO */
}; };
enum protocolEnum { enum protocolEnum {
......
...@@ -3598,19 +3598,21 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3598,19 +3598,21 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
char ntlm_session_key[CIFS_SESS_KEY_SIZE]; char ntlm_session_key[CIFS_SESS_KEY_SIZE];
bool ntlmv2_flag = false; bool ntlmv2_flag = false;
int first_time = 0; int first_time = 0;
struct TCP_Server_Info *server = pSesInfo->server;
/* what if server changes its buffer size after dropping the session? */ /* what if server changes its buffer size after dropping the session? */
if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { if (server->maxBuf == 0) /* no need to send on reconnect */ {
rc = CIFSSMBNegotiate(xid, pSesInfo); rc = CIFSSMBNegotiate(xid, pSesInfo);
if (rc == -EAGAIN) /* retry only once on 1st time connection */ { if (rc == -EAGAIN) {
/* retry only once on 1st time connection */
rc = CIFSSMBNegotiate(xid, pSesInfo); rc = CIFSSMBNegotiate(xid, pSesInfo);
if (rc == -EAGAIN) if (rc == -EAGAIN)
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
} }
if (rc == 0) { if (rc == 0) {
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if (pSesInfo->server->tcpStatus != CifsExiting) if (server->tcpStatus != CifsExiting)
pSesInfo->server->tcpStatus = CifsGood; server->tcpStatus = CifsGood;
else else
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -3623,23 +3625,22 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3623,23 +3625,22 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
goto ss_err_exit; goto ss_err_exit;
pSesInfo->flags = 0; pSesInfo->flags = 0;
pSesInfo->capabilities = pSesInfo->server->capabilities; pSesInfo->capabilities = server->capabilities;
if (linuxExtEnabled == 0) if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX); pSesInfo->capabilities &= (~CAP_UNIX);
/* pSesInfo->sequence_number = 0;*/ /* pSesInfo->sequence_number = 0;*/
cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
pSesInfo->server->secMode, server->secMode, server->capabilities, server->timeAdj));
pSesInfo->server->capabilities,
pSesInfo->server->timeAdj));
if (experimEnabled < 2) if (experimEnabled < 2)
rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
else if (extended_security else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) { && (server->secType == NTLMSSP)) {
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} else if (extended_security } else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) { && (server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup")); cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
nls_info); nls_info);
...@@ -3668,12 +3669,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3668,12 +3669,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
} else { } else {
SMBNTencrypt(pSesInfo->password, SMBNTencrypt(pSesInfo->password,
pSesInfo->server->cryptKey, server->cryptKey,
ntlm_session_key); ntlm_session_key);
if (first_time) if (first_time)
cifs_calculate_mac_key( cifs_calculate_mac_key(
&pSesInfo->server->mac_signing_key, &server->mac_signing_key,
ntlm_session_key, ntlm_session_key,
pSesInfo->password); pSesInfo->password);
} }
...@@ -3686,13 +3687,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3686,13 +3687,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
nls_info); nls_info);
} }
} else { /* old style NTLM 0.12 session setup */ } else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, SMBNTencrypt(pSesInfo->password, server->cryptKey,
ntlm_session_key); ntlm_session_key);
if (first_time) if (first_time)
cifs_calculate_mac_key( cifs_calculate_mac_key(&server->mac_signing_key,
&pSesInfo->server->mac_signing_key, ntlm_session_key,
ntlm_session_key, pSesInfo->password); pSesInfo->password);
rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
} }
......
...@@ -546,7 +546,8 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -546,7 +546,8 @@ int cifs_get_inode_info(struct inode **pinode,
if ((inode->i_mode & S_IWUGO) == 0 && if ((inode->i_mode & S_IWUGO) == 0 &&
(attr & ATTR_READONLY) == 0) (attr & ATTR_READONLY) == 0)
inode->i_mode |= (S_IWUGO & default_mode); inode->i_mode |= (S_IWUGO & default_mode);
inode->i_mode &= ~S_IFMT;
inode->i_mode &= ~S_IFMT;
} }
/* clear write bits if ATTR_READONLY is set */ /* clear write bits if ATTR_READONLY is set */
if (attr & ATTR_READONLY) if (attr & ATTR_READONLY)
......
...@@ -505,7 +505,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -505,7 +505,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else } else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else if (type == Kerberos) { } else if (type == Kerberos || type == MSKerberos) {
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
struct cifs_spnego_msg *msg; struct cifs_spnego_msg *msg;
spnego_key = cifs_get_spnego_key(ses); spnego_key = cifs_get_spnego_key(ses);
...@@ -516,6 +516,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -516,6 +516,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
} }
msg = spnego_key->payload.data; msg = spnego_key->payload.data;
/* check version field to make sure that cifs.upcall is
sending us a response in an expected form */
if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
cERROR(1, ("incorrect version of cifs.upcall (expected"
" %d but got %d)",
CIFS_SPNEGO_UPCALL_VERSION, msg->version));
rc = -EKEYREJECTED;
goto ssetup_exit;
}
/* bail out if key is too long */ /* bail out if key is too long */
if (msg->sesskey_len > if (msg->sesskey_len >
sizeof(ses->server->mac_signing_key.data.krb5)) { sizeof(ses->server->mac_signing_key.data.krb5)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment