Commit bed8ce47 authored by Steve French's avatar Steve French

Merge bk://linux.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
parents ccfd6724 31d35680
This module, cifs, is a filesystem that implements the SMB/CIFS This is the client VFS module for the Common Internet File System
protocol, which is the protocol used by Windows based operating systems (CIFS) protocol which is the successor to the Server Message Block
(including Windows 2000 and its successors) as well as Samba, OS/2 and (SMB) protocol, the native file sharing mechanism for most early
many others operating systems and network file server appliances. The PC operating systems. CIFS is fully supported by current network
Cifs VFS filesystem module is designed to work well with servers that file servers such as Windows 2000, Windows 2003 (including
implement the newer versions (dialects) of the SMB/CIFS protocol such as Windows XP) as well by Samba (which provides excellent CIFS
Samba, the program written by Andrew Tridgell that turns any Unix host server support for Linux and many other operating systems), so
into a file server for DOS or Windows clients, as well as Windows NT, this network filesystem client can mount to a wide variety of
Windows 2000 and its successors. It is not designed to handle older smb servers. The smbfs module should be used instead of this cifs module
servers well, those that implement older versions of the dialect (such for mounting to older SMB servers such as OS/2. The smbfs and cifs
as OS/2 or Windows 95), for this purpose use smbfs. modules can coexist and do not conflict. The CIFS VFS filesystem
module is designed to work well with servers that implement the
This module can support mounting without a mount helper program. The newer versions (dialects) of the SMB/CIFS protocol such as Samba,
mount syntax is: the program written by Andrew Tridgell that turns any Unix host
mount //server_ip/share_name /mnt -o user=username,password=your_password into a SMB/CIFS file server.
where "username", "your_password" and "server_ip" and "share_name" The intent of this module is to provide the most advanced network
should be replaced with specific values (supplied by the user) e.g. file system function for CIFS compliant servers, including better
mount //9.53.216.16/public /mnt -o user=jsmith,password=openup POSIX compliance, secure per-user session establishment, high
performance safe distributed caching (oplock), optional packet
This cifs implementation is designed to handle network caching (safely) signing, large files, Unicode support and other internationalization
as well as to implement locking, large file (64 bit access), distributed improvements. Since both Samba server and this filesystem client support
file system ("dfs") and other advanced protocol features. It also the CIFS Unix extensions, the combination can provide a reasonable
implements the SNIA standard for Unix extensions to CIFS (when alternative to NFSv4 for fileserving in some Linux to Linux environments,
communicating with servers such as Samba 2.2.3 or later which support it). not just in Linux to Windows environments.
For more information contact sfrench@us.ibm.com This filesystem has an optional mount utility (mount.cifs) that can
be obtained from the project page and installed in the path in the same
Cifs is an SMB client (or gateway). For more info on the SMB/CIFS directory with the other mount helpers (such as mount.smbfs).
protocol and Samba, including documentation, please go to Mounting using the cifs filesystem without installing the mount helper
http://www.samba.org/ and then on to your nearest mirror. For more requires specifying the server's ip address.
information about the cifs vfs, go to the project page at:
For Linux 2.4:
mount //anything/here /mnt_target -o
user=username,pass=password,unc=//ip_address_of_server/sharename
For Linux 2.5:
mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
For more information on the module see the project page at
http://us1.samba.org/samba/Linux_CIFS_client.html http://us1.samba.org/samba/Linux_CIFS_client.html
For more information on CIFS see:
http://www.snia.org/tech_activities/CIFS
or the Samba site:
http://www.samba.org
...@@ -89,8 +89,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -89,8 +89,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
ses->serverOS, ses->serverNOS, ses->capabilities); ses->serverOS, ses->serverNOS, ses->capabilities);
buf += length; buf += length;
if(ses->server) if(ses->server)
buf += sprintf(buf, "\tLocal Users To Same Server: %d ", buf += sprintf(buf, "\tLocal Users To Same Server: %d SecMode: 0x%x",
atomic_read(&ses->server->socketUseCount)); atomic_read(&ses->server->socketUseCount),ses->server->secMode);
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
sprintf(buf, "\n"); sprintf(buf, "\n");
...@@ -590,6 +590,8 @@ packet_signing_enabled_write(struct file *file, const char *buffer, ...@@ -590,6 +590,8 @@ packet_signing_enabled_write(struct file *file, const char *buffer,
sign_CIFS_PDUs = 0; sign_CIFS_PDUs = 0;
else if (c == '1' || c == 'y' || c == 'Y') else if (c == '1' || c == 'y' || c == 'Y')
sign_CIFS_PDUs = 1; sign_CIFS_PDUs = 1;
else if (c == '2')
sign_CIFS_PDUs = 2;
return count; return count;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "cifsglob.h" #include "cifsglob.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "md5.h" #include "md5.h"
#include "cifs_unicode.h"
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */ /* Calculate and return the CIFS signature based on the mac key and the smb pdu */
/* the 16 byte signature must be allocated by the caller */ /* the 16 byte signature must be allocated by the caller */
...@@ -133,8 +134,68 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password) ...@@ -133,8 +134,68 @@ int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
if ((key == NULL) || (rn == NULL) || (password == NULL)) if ((key == NULL) || (rn == NULL) || (password == NULL))
return -EINVAL; return -EINVAL;
E_md4hash(password, temp_key); /* BB may have to do another md4 of it */ E_md4hash(password, temp_key);
mdfour(key,temp_key,16); mdfour(key,temp_key,16);
memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
return 0; return 0;
} }
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
{
char temp_hash[16];
struct HMACMD5Context ctx;
char * ucase_buf;
wchar_t * unicode_buf;
unsigned int i,user_name_len,dom_name_len;
if(ses)
return -EINVAL;
E_md4hash(ses->password_with_pad, temp_hash);
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
user_name_len = strlen(ses->userName);
if(user_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
dom_name_len = strlen(ses->domainName);
if(dom_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
for(i=0;i<user_name_len;i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
ucase_buf[i] = 0;
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len] = 0;
user_name_len++;
for(i=0;i<dom_name_len;i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
ucase_buf[i] = 0;
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len + dom_name_len] = 0;
hmac_md5_update((const unsigned char *) unicode_buf,
(user_name_len+dom_name_len)*2,&ctx);
hmac_md5_final(ses->mac_signing_key,&ctx);
kfree(ucase_buf);
kfree(unicode_buf);
return 0;
}
void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
{
struct HMACMD5Context context;
memcpy(v2_session_response + 8, ses->server->cryptKey,8);
/* gen_blob(v2_session_response + 16); */
hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
hmac_md5_update(ses->server->cryptKey,8,&context);
/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
hmac_md5_final(v2_session_response,&context);
}
...@@ -301,6 +301,7 @@ struct inode_operations cifs_dir_inode_ops = { ...@@ -301,6 +301,7 @@ struct inode_operations cifs_dir_inode_ops = {
/* revalidate:cifs_revalidate, */ /* revalidate:cifs_revalidate, */
.setattr = cifs_setattr, .setattr = cifs_setattr,
.symlink = cifs_symlink, .symlink = cifs_symlink,
.mknod = cifs_mknod,
}; };
struct inode_operations cifs_file_inode_ops = { struct inode_operations cifs_file_inode_ops = {
......
...@@ -50,6 +50,7 @@ extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *) ...@@ -50,6 +50,7 @@ extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *)
extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *); extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *); extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
extern int cifs_mkdir(struct inode *, struct dentry *, int); extern int cifs_mkdir(struct inode *, struct dentry *, int);
extern int cifs_rmdir(struct inode *, struct dentry *); extern int cifs_rmdir(struct inode *, struct dentry *);
extern int cifs_rename(struct inode *, struct dentry *, struct inode *, extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
......
...@@ -88,8 +88,7 @@ extern int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -88,8 +88,7 @@ extern int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
const struct nls_table *); const struct nls_table *);
extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid, extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid,
struct cifsSesInfo *ses, char *ntlm_session_key, struct cifsSesInfo *ses, char *ntlm_session_key,
char *lanman_session_key,int ntlmv2_flag, int ntlmv2_flag, const struct nls_table *);
const struct nls_table *);
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const char *tree, struct cifsTconInfo *tcon, const char *tree, struct cifsTconInfo *tcon,
...@@ -156,7 +155,7 @@ extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, ...@@ -156,7 +155,7 @@ extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag); __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid, char *full_path, __u64 mode, __u64 uid,
__u64 gid, const struct nls_table *nls_codepage); __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
const char *newName, const char *newName,
...@@ -229,8 +228,8 @@ extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); ...@@ -229,8 +228,8 @@ extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key, extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number); __u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
/* BB routines below not implemented yet BB */ extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
extern int CIFSBuildServerList(int xid, char *serverBufferList, extern int CIFSBuildServerList(int xid, char *serverBufferList,
int recordlength, int *entries, int recordlength, int *entries,
......
...@@ -2299,7 +2299,7 @@ CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName, ...@@ -2299,7 +2299,7 @@ CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
int int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
char *fileName, __u64 mode, __u64 uid, __u64 gid, char *fileName, __u64 mode, __u64 uid, __u64 gid,
const struct nls_table *nls_codepage) dev_t device, const struct nls_table *nls_codepage)
{ {
TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL;
...@@ -2358,6 +2358,9 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, ...@@ -2358,6 +2358,9 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
pSMB->hdr.smb_buf_length += pSMB->ByteCount; pSMB->hdr.smb_buf_length += pSMB->ByteCount;
data_offset->Uid = cpu_to_le64(uid); data_offset->Uid = cpu_to_le64(uid);
data_offset->Gid = cpu_to_le64(gid); data_offset->Gid = cpu_to_le64(gid);
/* better to leave device as zero when it is */
data_offset->DevMajor = cpu_to_le64(MAJOR(device));
data_offset->DevMinor = cpu_to_le64(MINOR(device));
data_offset->Permissions = cpu_to_le64(mode); data_offset->Permissions = cpu_to_le64(mode);
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
......
...@@ -634,7 +634,6 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, ...@@ -634,7 +634,6 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info) int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info)
{ {
int rc = 0; int rc = 0;
char session_key[CIFS_SESSION_KEY_SIZE];
char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
int ntlmv2_flag = FALSE; int ntlmv2_flag = FALSE;
...@@ -666,26 +665,34 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab ...@@ -666,26 +665,34 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
nls_info); nls_info);
if (!rc) { if (!rc) {
if(ntlmv2_flag) { if(ntlmv2_flag) {
cFYI(1,("Able to use the more secure NTLM version 2 password hash")); char * v2_response;
/* SMBNTv2encrypt( ...); */ /* BB fix this up - cFYI(1,("Can use more secure NTLM version 2 password hash"));
and note that Samba client equivalent looks wrong */ CalcNTLMv2_partial_mac_key(pSesInfo,
nls_info);
v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
if(v2_response) {
CalcNTLMv2_response(pSesInfo,v2_response);
/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
kfree(v2_response);
/* BB Put dummy sig in SessSetup PDU? */
} else } else
SMBNTencrypt(pSesInfo->password_with_pad, rc = -ENOMEM;
pSesInfo->server->cryptKey,ntlm_session_key);
/* BB add call to save MAC key here BB */ } else {
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,
ntlm_session_key);
cifs_calculate_mac_key(pSesInfo->mac_signing_key,
ntlm_session_key,
pSesInfo->password_with_pad);
}
/* for better security the weaker lanman hash not sent /* for better security the weaker lanman hash not sent
in AuthSessSetup so why bother calculating it */ in AuthSessSetup so we no longer calculate it */
/* toUpper(nls_info,
password_with_pad);
SMBencrypt(password_with_pad,
pSesInfo->server->cryptKey, session_key); */
rc = CIFSNTLMSSPAuthSessSetup(xid, rc = CIFSNTLMSSPAuthSessSetup(xid,
pSesInfo, pSesInfo,
ntlm_session_key, ntlm_session_key,
session_key,
ntlmv2_flag, ntlmv2_flag,
nls_info); nls_info);
} }
...@@ -694,7 +701,8 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab ...@@ -694,7 +701,8 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
pSesInfo->server->cryptKey, pSesInfo->server->cryptKey,
ntlm_session_key); ntlm_session_key);
cifs_calculate_mac_key(pSesInfo->mac_signing_key, ntlm_session_key, pSesInfo->password_with_pad); cifs_calculate_mac_key(pSesInfo->mac_signing_key,
ntlm_session_key, pSesInfo->password_with_pad);
rc = CIFSSessSetup(xid, pSesInfo, rc = CIFSSessSetup(xid, pSesInfo,
ntlm_session_key, nls_info); ntlm_session_key, nls_info);
} }
...@@ -1297,7 +1305,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -1297,7 +1305,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
int bytes_returned = 0; int bytes_returned = 0;
int len; int len;
cFYI(1, ("In v2 sesssetup ")); cFYI(1, ("In spnego sesssetup "));
smb_buffer = buf_get(); smb_buffer = buf_get();
if (smb_buffer == 0) { if (smb_buffer == 0) {
...@@ -1605,7 +1613,9 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -1605,7 +1613,9 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob->NegotiateFlags = SecurityBlob->NegotiateFlags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_128; /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
if(sign_CIFS_PDUs)
SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
if(ntlmv2_support) if(ntlmv2_support)
SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
/* setup pointers to domain name and workstation name */ /* setup pointers to domain name and workstation name */
...@@ -1725,6 +1735,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -1725,6 +1735,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
CIFS_CRYPTO_KEY_SIZE); CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2) if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
*pNTLMv2_flag = TRUE; *pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
|| (sign_CIFS_PDUs > 1))
ses->server->secMode |=
SECMODE_SIGN_REQUIRED;
if ((SecurityBlob2->NegotiateFlags &
NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
ses->server->secMode |=
SECMODE_SIGN_ENABLED;
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) { if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) { if ((long) (bcc_ptr) % 2) {
remaining_words = remaining_words =
...@@ -1868,7 +1889,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -1868,7 +1889,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
int int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *ntlm_session_key, char *lanman_session_key, int ntlmv2_flag, char *ntlm_session_key, int ntlmv2_flag,
const struct nls_table *nls_codepage) const struct nls_table *nls_codepage)
{ {
struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer;
...@@ -1934,7 +1955,9 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -1934,7 +1955,9 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
SecurityBlob->NegotiateFlags = SecurityBlob->NegotiateFlags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
0x80000000 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_128; 0x80000000 | NTLMSSP_NEGOTIATE_128;
if(sign_CIFS_PDUs)
SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
if(ntlmv2_flag) if(ntlmv2_flag)
SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/namei.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -125,6 +126,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -125,6 +126,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int rc = -ENOENT; int rc = -ENOENT;
int xid; int xid;
int oplock = REQ_OPLOCK; int oplock = REQ_OPLOCK;
int desiredAccess = GENERIC_ALL;
__u16 fileHandle; __u16 fileHandle;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
...@@ -138,10 +140,23 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -138,10 +140,23 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(nd) {
cFYI(1,("In create nd flags = 0x%x for %s",nd->flags,full_path));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
desiredAccess = GENERIC_WRITE;
else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR)
desiredAccess = GENERIC_ALL;
}
/* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */ /* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF, GENERIC_ALL rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
/* 0x20197 was used previously */ , CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, cifs_sb->local_nls); &fileHandle, &oplock, cifs_sb->local_nls);
if (rc) { if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc)); cFYI(1, ("cifs_create returned 0x%x ", rc));
...@@ -178,6 +193,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -178,6 +193,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return rc; return rc;
} }
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number)
{
int rc = -EPERM;
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
struct inode * newinode = NULL;
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if (pTcon->ses->capabilities & CAP_UNIX) {
rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, current->euid, current->egid,
device_number, cifs_sb->local_nls);
if(!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb);
direntry->d_op = &cifs_dentry_ops;
if(rc == 0)
d_instantiate(direntry, newinode);
}
}
if (full_path)
kfree(full_path);
FreeXid(xid);
return rc;
}
struct dentry * struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
{ {
...@@ -208,6 +260,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -208,6 +260,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
} }
cFYI(1, cFYI(1,
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode)); (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
if(nd) { /* BB remove begin */
cFYI(1,("In lookup nd flags = 0x%x",nd->flags));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
}
/* BB remove end BB */
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path, rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb); parent_dir_inode->i_sb);
...@@ -269,6 +328,12 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) ...@@ -269,6 +328,12 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ /* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
if(nd) { /* BB remove begin */
cFYI(1,("In d_revalidate nd flags = 0x%x",nd->flags));
cFYI(1,("Intent flags: 0x%x", nd->intent.open.flags));
}
/* BB remove end BB */
if (direntry->d_inode) { if (direntry->d_inode) {
if (cifs_revalidate(direntry)) { if (cifs_revalidate(direntry)) {
/* unlock_kernel(); */ /* unlock_kernel(); */
......
...@@ -52,12 +52,12 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -52,12 +52,12 @@ cifs_open(struct inode *inode, struct file *file)
xid = GetXid(); xid = GetXid();
cFYI(1, (" inode = 0x%p file flags are %x", inode, file->f_flags));
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
cFYI(1, (" inode = 0x%p file flags are %x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
else if ((file->f_flags & O_ACCMODE) == O_WRONLY) else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
...@@ -125,6 +125,7 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -125,6 +125,7 @@ cifs_open(struct inode *inode, struct file *file)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
(__u64)-1, (__u64)-1,
(__u64)-1, (__u64)-1,
0 /* dev */,
cifs_sb->local_nls); cifs_sb->local_nls);
else {/* BB implement via Windows security descriptors */ else {/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
......
...@@ -397,6 +397,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -397,6 +397,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1, (__u64)-1,
(__u64)-1, (__u64)-1,
0 /* dev_t */,
cifs_sb->local_nls); cifs_sb->local_nls);
else { /* BB to be implemented via Windows secrty descriptors*/ else { /* BB to be implemented via Windows secrty descriptors*/
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
...@@ -702,7 +703,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -702,7 +703,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
cifs_sb->local_nls); 0 /* dev_t */, cifs_sb->local_nls);
else if (attrs->ia_valid & ATTR_MODE) { else if (attrs->ia_valid & ATTR_MODE) {
if((mode & S_IWUGO) == 0) /* not writeable */ { if((mode & S_IWUGO) == 0) /* not writeable */ {
if((cifsInode->cifsAttrs & ATTR_READONLY) == 0) if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
......
...@@ -470,58 +470,3 @@ int SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, ...@@ -470,58 +470,3 @@ int SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
return TRUE; return TRUE;
} }
/***********************************************************
SMB signing - setup the MAC key.
************************************************************/
void
cli_calculate_mac_key(__u8 * mac_key, int *pmac_key_len,
const char *ntpasswd, const unsigned char resp[24])
{
/* Get first 16 bytes. */
E_md4hash(ntpasswd, mac_key);
memcpy(mac_key + 16, resp, 24);
*pmac_key_len = 40;
/* Reset the sequence number in case we had a previous (aborted) attempt */
/* cli->sign_info.send_seq_num = 0; */
}
/***********************************************************
SMB signing - calculate a MAC to send.
************************************************************/
void
cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key,
int mac_key_len, __u32 * send_seq_num,
__u32 * reply_seq_num)
{
unsigned char calc_md5_mac[16];
struct MD5Context md5_ctx;
/* if (!cli->sign_info.use_smb_signing) {
return;
} */
/*
* Firstly put the sequence number into the first 4 bytes.
* and zero out the next 4 bytes.
*/
/*
SIVAL(outbuf, smb_ss_field, *send_seq_num);
SIVAL(outbuf, smb_ss_field + 4, 0); */
/* Calculate the 16 byte MAC and place first 8 bytes into the field. */
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, mac_key, mac_key_len);
MD5Update(&md5_ctx, outbuf->Protocol,
be32_to_cpu(outbuf->smb_buf_length));
MD5Final(calc_md5_mac, &md5_ctx);
memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
(*send_seq_num)++;
*reply_seq_num = *send_seq_num;
(*send_seq_num)++;
}
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