提交 789c56b7 编写于 作者: L 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: (24 commits)
  [CIFS] merge conflict in fs/cifs/export.c
  [CIFS] Allow disabling CIFS Unix Extensions as mount option
  [CIFS] More whitespace/formatting fixes (noticed by checkpatch)
  [CIFS] Typo in previous patch
  [CIFS] zero_user_page() conversions
  [CIFS] use simple_prepare_write to zero page data
  [CIFS] Fix build break - inet.h not included when experimental ifdef off
  [CIFS] Add support for new POSIX unlink
  [CIFS] whitespace/formatting fixes
  [CIFS] Fix oops in cifs_create when nfsd server exports cifs mount
  [CIFS] whitespace cleanup
  [CIFS] Fix packet signatures for NTLMv2 case
  [CIFS] more whitespace fixes
  [CIFS] more whitespace cleanup
  [CIFS] whitespace cleanup
  [CIFS] whitespace cleanup
  [CIFS] ipv6 support no longer experimental
  [CIFS] Mount should fail if server signing off but client mount option requires it
  [CIFS] whitespace fixes
  [CIFS] Fix sign mount option and sign proc config setting
  ...
Version 1.50
------------
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
done with "serverino" mount option). Add support for POSIX Unlink
(helps with certain sharing violation cases when server such as
Samba supports newer POSIX CIFS Protocol Extensions).
Version 1.49
------------
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
......@@ -8,7 +15,11 @@ when Unix Extensions were ignored). This allows users to override the
default uid and gid for files when they are certain that the uids or
gids on the server do not match those of the client. Make "sec=none"
mount override username (so that null user connection is attempted)
to match what documentation said.
to match what documentation said. Support for very large reads, over 127K,
available to some newer servers (such as Samba 3.0.26 and later but
note that it also requires setting CIFSMaxBufSize at module install
time to a larger value which may hurt performance in some cases).
Make sign option force signing (or fail if server does not support it).
Version 1.48
------------
......
......@@ -301,10 +301,21 @@ A partial list of the supported mount options follows:
during the local client kernel build will be used.
If server does not support Unicode, this parameter is
unused.
rsize default read size (usually 16K)
wsize default write size (usually 16K, 32K is often better over GigE)
maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
pages)
rsize default read size (usually 16K). The client currently
can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
defaults to 16K and may be changed (from 8K to the maximum
kmalloc size allowed by your kernel) at module install time
for cifs.ko. Setting CIFSMaxBufSize to a very large value
will cause cifs to use more memory and may reduce performance
in some cases. To use rsize greater than 127K (the original
cifs protocol maximum) also requires that the server support
a new Unix Capability flag (for very large read) which some
newer servers (e.g. Samba 3.0.26 or later) do. rsize can be
set from a minimum of 2048 to a maximum of 130048 (127K or
CIFSMaxBufSize, whichever is smaller)
wsize default write size (default 57344)
maximum wsize currently allowed by CIFS is 57344 (fourteen
4096 byte pages)
rw mount the network share read-write (note that the
server may still consider the share read-only)
ro mount network share read-only
......@@ -359,7 +370,7 @@ A partial list of the supported mount options follows:
Note that this does not affect the normal ACL check on the
target machine done by the server software (of the server
ACL against the user name provided at mount time).
serverino Use servers inode numbers instead of generating automatically
serverino Use server's inode numbers instead of generating automatically
incrementing inode numbers on the client. Although this will
make it easier to spot hardlinked files (as they will have
the same inode numbers) and inode numbers may be persistent,
......@@ -367,12 +378,11 @@ A partial list of the supported mount options follows:
are unique if multiple server side mounts are exported under a
single share (since inode numbers on the servers might not
be unique if multiple filesystems are mounted under the same
shared higher level directory). Note that this requires that
the server support the CIFS Unix Extensions as other servers
do not return a unique IndexNumber on SMB FindFirst (most
servers return zero as the IndexNumber). Parameter has no
effect to Windows servers and others which do not support the
CIFS Unix Extensions.
shared higher level directory). Note that some older
(e.g. pre-Windows 2000) do not support returning UniqueIDs
or the CIFS Unix Extensions equivalent and for those
this mount option will have no effect. Exporting cifs mounts
under nfsd requires this mount option on the cifs mount.
noserverino Client generates inode numbers (rather than using the actual one
from the server) by default.
setuids If the CIFS Unix extensions are negotiated with the server
......@@ -582,10 +592,10 @@ the start of smb requests and responses can be enabled via:
echo 1 > /proc/fs/cifs/traceSMB
Two other experimental features are under development and to test
require enabling CONFIG_CIFS_EXPERIMENTAL
Two other experimental features are under development. To test these
requires enabling CONFIG_CIFS_EXPERIMENTAL
More efficient write operations
ipv6 enablement
DNOTIFY fcntl: needed for support of directory change
notification and perhaps later for file leases)
......
......@@ -18,9 +18,9 @@ better)
d) Kerberos/SPNEGO session setup support - (started)
e) More testing of NTLMv2 authentication (mostly implemented - double check
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
fs/cifs/connect.c)
e) Cleanup now unneeded SessSetup code in
fs/cifs/connect.c and add back in NTLMSSP code if any servers
need it
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
......@@ -106,6 +106,12 @@ but recognizes them
succeed but still return access denied (appears to be Windows
server not cifs client problem) and has not been reproduced recently.
NTFS partitions do not have this problem.
4) Unix/POSIX capabilities are reset after reconnection, and affect
a few fields in the tree connection but we do do not know which
superblocks to apply these changes to. We should probably walk
the list of superblocks to set these. Also need to check the
flags on the second mount to the same share, and see if we
can do the same trick that NFS does to remount duplicate shares.
Misc testing to do
==================
......
/*
/*
* The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
* turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
*
*
* Copyright (c) 2000 RP Internet (www.rpi.net.au).
*
* This program is free software; you can redistribute it and/or modify
......@@ -80,7 +80,7 @@
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
/*
/*
* ASN.1 context.
*/
struct asn1_ctx {
......@@ -190,7 +190,7 @@ asn1_header_decode(struct asn1_ctx *ctx,
unsigned char **eoc,
unsigned int *cls, unsigned int *con, unsigned int *tag)
{
unsigned int def = 0;
unsigned int def = 0;
unsigned int len = 0;
if (!asn1_id_decode(ctx, cls, con, tag))
......@@ -331,7 +331,7 @@ static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
*integer |= ch;
}
return 1;
}
}
static unsigned char
asn1_octets_decode(struct asn1_ctx *ctx,
......@@ -376,7 +376,7 @@ asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
return 1;
}
static int
static int
asn1_oid_decode(struct asn1_ctx *ctx,
unsigned char *eoc, unsigned long **oid, unsigned int *len)
{
......@@ -459,7 +459,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned int cls, con, tag, oidlen, rc;
int use_ntlmssp = FALSE;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
......@@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
......@@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
......@@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length,
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) {
cFYI(1,
("Error 1 decoding negTokenInit header exit 2"));
("Error decoding negTokenInit hdr exit2"));
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
if(rc) {
if (rc) {
cFYI(1,
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
oidlen, *oid, *(oid + 1), *(oid + 2),
*(oid + 3)));
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN);
("OID len = %d oid = 0x%lx 0x%lx "
"0x%lx 0x%lx",
oidlen, *oid, *(oid + 1),
*(oid + 2), *(oid + 3)));
rc = compare_oid(oid, oidlen,
NTLMSSP_OID, NTLMSSP_OID_LEN);
kfree(oid);
if (rc)
use_ntlmssp = TRUE;
}
} else {
cFYI(1,("This should be an oid what is going on? "));
cFYI(1, ("Should be an oid what is going on?"));
}
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part of negTokenInit exit 3"));
("Error decoding last part negTokenInit exit3"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
/* tag = 3 indicating mechListMIC */
cFYI(1,
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
......@@ -573,7 +577,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part of negTokenInit exit 5"));
("Error decoding last part negTokenInit exit5"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
......@@ -584,7 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part of negTokenInit exit 7"));
("Error decoding last part negTokenInit exit 7"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
cFYI(1,
......@@ -594,20 +598,21 @@ decode_negTokenInit(unsigned char *security_blob, int length,
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("Error decoding last part of negTokenInit exit 9"));
("Error decoding last part negTokenInit exit9"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) {
cFYI(1,
("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
cFYI(1, ("Need to call asn1_octets_decode() function for %s",
ctx.pointer)); /* is this UTF-8 or ASCII? */
}
/* if (use_kerberos)
*secType = Kerberos
/* if (use_kerberos)
*secType = Kerberos
else */
if (use_ntlmssp) {
*secType = NTLMSSP;
......
......@@ -58,7 +58,7 @@ cifs_dump_mem(char *label, void *data, int length)
}
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb)
void cifs_dump_detail(struct smb_hdr *smb)
{
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
......@@ -67,10 +67,10 @@ void cifs_dump_detail(struct smb_hdr * smb)
}
void cifs_dump_mids(struct TCP_Server_Info * server)
void cifs_dump_mids(struct TCP_Server_Info *server)
{
struct list_head *tmp;
struct mid_q_entry * mid_entry;
struct mid_q_entry *mid_entry;
if (server == NULL)
return;
......@@ -114,12 +114,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
{
struct list_head *tmp;
struct list_head *tmp1;
struct mid_q_entry * mid_entry;
struct mid_q_entry *mid_entry;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
int i;
int length = 0;
char * original_buf = buf;
char *original_buf = buf;
*beginBuffer = buf + offset;
......@@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
(ses->serverNOS == NULL)) {
buf += sprintf(buf, "\nentry for %s not fully "
"displayed\n\t", ses->serverName);
} else {
length =
sprintf(buf,
......@@ -901,90 +900,14 @@ security_flags_write(struct file *file, const char __user *buffer,
}
/* flags look ok - update the global security flags for cifs module */
extended_security = flags;
if (extended_security & CIFSSEC_MUST_SIGN) {
/* requiring signing implies signing is allowed */
extended_security |= CIFSSEC_MAY_SIGN;
cFYI(1, ("packet signing now required"));
} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
cFYI(1, ("packet signing disabled"));
}
/* BB should we turn on MAY flags for other MUST options? */
return count;
}
/* static int
ntlmv2_enabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", ntlmv2_support);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
ntlmv2_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
ntlmv2_support = 0;
else if (c == '1' || c == 'y' || c == 'Y')
ntlmv2_support = 1;
else if (c == '2')
ntlmv2_support = 2;
return count;
}
static int
packet_signing_enabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", sign_CIFS_PDUs);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
packet_signing_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
sign_CIFS_PDUs = 0;
else if (c == '1' || c == 'y' || c == 'Y')
sign_CIFS_PDUs = 1;
else if (c == '2')
sign_CIFS_PDUs = 2;
return count;
} */
#endif
......@@ -43,6 +43,6 @@ struct cifs_sb_info {
mode_t mnt_dir_mode;
int mnt_cifs_flags;
int prepathlen;
char * prepath;
char *prepath;
};
#endif /* _CIFS_FS_SB_H */
......@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
{
int charlen;
int i;
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
......
......@@ -5,20 +5,20 @@
* Convert a unicode character to upper or lower case using
* compressed tables.
*
* Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
* Copyright (c) International Business Machines Corp., 2000,2007
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
......@@ -70,7 +70,7 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
* Address of the first string
*/
static inline wchar_t *
UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
{
wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
......@@ -88,7 +88,7 @@ UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
* or NULL if the character is not in the string
*/
static inline wchar_t *
UniStrchr(const wchar_t * ucs, wchar_t uc)
UniStrchr(const wchar_t *ucs, wchar_t uc)
{
while ((*ucs != uc) && *ucs)
ucs++;
......@@ -107,7 +107,7 @@ UniStrchr(const wchar_t * ucs, wchar_t uc)
* > 0: First string is greater than second
*/
static inline int
UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
{
while ((*ucs1 == *ucs2) && *ucs1) {
ucs1++;
......@@ -120,7 +120,7 @@ UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
* UniStrcpy: Copy a string
*/
static inline wchar_t *
UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
{
wchar_t *anchor = ucs1; /* save the start of result string */
......@@ -132,7 +132,7 @@ UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
* UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
*/
static inline size_t
UniStrlen(const wchar_t * ucs1)
UniStrlen(const wchar_t *ucs1)
{
int i = 0;
......@@ -142,10 +142,11 @@ UniStrlen(const wchar_t * ucs1)
}
/*
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
* string (length limited)
*/
static inline size_t
UniStrnlen(const wchar_t * ucs1, int maxlen)
UniStrnlen(const wchar_t *ucs1, int maxlen)
{
int i = 0;
......@@ -161,7 +162,7 @@ UniStrnlen(const wchar_t * ucs1, int maxlen)
* UniStrncat: Concatenate length limited string
*/
static inline wchar_t *
UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{
wchar_t *anchor = ucs1; /* save pointer to string 1 */
......@@ -179,7 +180,7 @@ UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncmp: Compare length limited string
*/
static inline int
UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{
if (!n)
return 0; /* Null strings are equal */
......@@ -194,7 +195,7 @@ UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncmp_le: Compare length limited string - native to little-endian
*/
static inline int
UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{
if (!n)
return 0; /* Null strings are equal */
......@@ -209,7 +210,7 @@ UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncpy: Copy length limited string with pad
*/
static inline wchar_t *
UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{
wchar_t *anchor = ucs1;
......@@ -226,7 +227,7 @@ UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncpy_le: Copy length limited string with pad to little-endian
*/
static inline wchar_t *
UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{
wchar_t *anchor = ucs1;
......@@ -247,7 +248,7 @@ UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* NULL if no matching string is found
*/
static inline wchar_t *
UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
{
const wchar_t *anchor1 = ucs1;
const wchar_t *anchor2 = ucs2;
......@@ -297,7 +298,7 @@ UniToupper(register wchar_t uc)
* UniStrupr: Upper case a unicode string
*/
static inline wchar_t *
UniStrupr(register wchar_t * upin)
UniStrupr(register wchar_t *upin)
{
register wchar_t *up;
......@@ -338,7 +339,7 @@ UniTolower(wchar_t uc)
* UniStrlwr: Lower case a unicode string
*/
static inline wchar_t *
UniStrlwr(register wchar_t * upin)
UniStrlwr(register wchar_t *upin)
{
register wchar_t *up;
......
......@@ -3,16 +3,16 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* uniupr.h - Unicode compressed case ranges
......@@ -53,7 +53,7 @@ signed char CifsUniUpperTable[512] = {
0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
-1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
};
......
......@@ -21,7 +21,7 @@
#include <linux/fs.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsglob.h"
#include "cifs_debug.h"
#include "md5.h"
#include "cifs_unicode.h"
......@@ -29,54 +29,57 @@
#include <linux/ctype.h>
#include <linux/random.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 SMB PDU */
/* the 16 byte signature must be allocated by the caller */
/* Note we only use the 1st eight bytes */
/* Note that the smb header signature field on input contains the
/* Note that the smb header signature field on input contains the
sequence number before this function is called */
extern void mdfour(unsigned char *out, unsigned char *in, int n);
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
const char * key, char * signature)
unsigned char *p24);
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
const struct mac_key *key, char *signature)
{
struct MD5Context context;
if((cifs_pdu == NULL) || (signature == NULL))
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL;
MD5Init(&context);
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
MD5Final(signature,&context);
MD5Update(&context, (char *)&key->data, key->len);
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
MD5Final(signature, &context);
return 0;
}
int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
__u32 * pexpected_response_sequence_number)
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
if((cifs_pdu == NULL) || (server == NULL))
if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL;
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc;
spin_lock(&GlobalMid_Lock);
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(server->sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0;
*pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++;
spin_unlock(&GlobalMid_Lock);
rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
if(rc)
rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
smb_signature);
if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
......@@ -84,115 +87,119 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
return rc;
}
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
const char * key, char * signature)
static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
const struct mac_key *key, char *signature)
{
struct MD5Context context;
int i;
if((iov == NULL) || (signature == NULL))
if ((iov == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL;
MD5Init(&context);
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
for(i=0;i<n_vec;i++) {
if(iov[i].iov_base == NULL) {
cERROR(1,("null iovec entry"));
MD5Update(&context, (char *)&key->data, key->len);
for (i = 0; i < n_vec; i++) {
if (iov[i].iov_base == NULL) {
cERROR(1, ("null iovec entry"));
return -EIO;
} else if(iov[i].iov_len == 0)
} else if (iov[i].iov_len == 0)
break; /* bail out if we are sent nothing to sign */
/* The first entry includes a length field (which does not get
/* The first entry includes a length field (which does not get
signed that occupies the first 4 bytes before the header */
if(i==0) {
if (i == 0) {
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */
MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
MD5Update(&context, iov[0].iov_base+4,
iov[0].iov_len-4);
} else
MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
}
MD5Final(signature,&context);
MD5Final(signature, &context);
return 0;
}
int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
__u32 * pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
struct smb_hdr * cifs_pdu = iov[0].iov_base;
struct smb_hdr *cifs_pdu = iov[0].iov_base;
if((cifs_pdu == NULL) || (server == NULL))
if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL;
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc;
spin_lock(&GlobalMid_Lock);
cifs_pdu->Signature.Sequence.SequenceNumber =
spin_lock(&GlobalMid_Lock);
cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(server->sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0;
cifs_pdu->Signature.Sequence.Reserved = 0;
*pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++;
spin_unlock(&GlobalMid_Lock);
*pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++;
spin_unlock(&GlobalMid_Lock);
rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
smb_signature);
if(rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
return rc;
if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
return rc;
}
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
__u32 expected_sequence_number)
int cifs_verify_signature(struct smb_hdr *cifs_pdu,
const struct mac_key *mac_key,
__u32 expected_sequence_number)
{
unsigned int rc;
char server_response_sig[8];
char what_we_think_sig_should_be[20];
if((cifs_pdu == NULL) || (mac_key == NULL))
if ((cifs_pdu == NULL) || (mac_key == NULL))
return -EINVAL;
if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
return 0;
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
struct smb_com_lock_req *pSMB =
(struct smb_com_lock_req *)cifs_pdu;
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
return 0;
}
/* BB what if signatures are supposed to be on for session but server does not
send one? BB */
/* BB what if signatures are supposed to be on for session but
server does not send one? BB */
/* Do not need to verify session setups with signature "BSRSPYL " */
if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
cFYI(1, ("dummy signature received for smb command 0x%x",
cifs_pdu->Command));
/* save off the origiginal signature so we can modify the smb and check
its signature against what the server sent */
memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(expected_sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0;
rc = cifs_calculate_signature(cifs_pdu, mac_key,
what_we_think_sig_should_be);
if(rc)
if (rc)
return rc;
/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
/* cifs_dump_mem("what we think it should be: ",
what_we_think_sig_should_be, 16); */
if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
return -EACCES;
else
return 0;
......@@ -200,89 +207,94 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
}
/* We fill in key by putting in 40 byte array which was allocated by caller */
int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *password)
{
char temp_key[16];
if ((key == NULL) || (rn == NULL))
return -EINVAL;
E_md4hash(password, temp_key);
mdfour(key,temp_key,16);
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
mdfour(key->data.ntlm, temp_key, 16);
memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE);
key->len = 40;
return 0;
}
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
const struct nls_table * nls_info)
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
const struct nls_table *nls_info)
{
char temp_hash[16];
struct HMACMD5Context ctx;
char * ucase_buf;
__le16 * unicode_buf;
unsigned int i,user_name_len,dom_name_len;
char *ucase_buf;
__le16 *unicode_buf;
unsigned int i, user_name_len, dom_name_len;
if(ses == NULL)
if (ses == NULL)
return -EINVAL;
E_md4hash(ses->password, 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)
if (user_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
if(ses->domainName == NULL)
if (ses->domainName == NULL)
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
dom_name_len = strlen(ses->domainName);
if(dom_name_len > MAX_USERNAME_SIZE)
if (dom_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
if(ucase_buf == NULL)
if (ucase_buf == NULL)
return -ENOMEM;
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
if(unicode_buf == NULL) {
if (unicode_buf == NULL) {
kfree(ucase_buf);
return -ENOMEM;
}
for(i=0;i<user_name_len;i++)
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);
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++)
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);
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);
(user_name_len+dom_name_len)*2, &ctx);
hmac_md5_final(ses->server->mac_signing_key,&ctx);
hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
kfree(ucase_buf);
kfree(unicode_buf);
return 0;
}
#ifdef CONFIG_CIFS_WEAK_PW_HASH
void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
{
int i;
char password_with_pad[CIFS_ENCPWD_SIZE];
if(ses->server == NULL)
if (ses->server == NULL)
return;
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
if(ses->password)
if (ses->password)
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
if(extended_security & CIFSSEC_MAY_PLNTXT) {
memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
if (extended_security & CIFSSEC_MAY_PLNTXT) {
memcpy(lnm_session_key, password_with_pad,
CIFS_ENCPWD_SIZE);
return;
}
......@@ -297,7 +309,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
utf8 and other multibyte codepages each need their own strupper
function since a byte at a time will ont work. */
for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
for (i = 0; i < CIFS_ENCPWD_SIZE; i++) {
password_with_pad[i] = toupper(password_with_pad[i]);
}
......@@ -307,19 +319,19 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
}
#endif /* CIFS_WEAK_PW_HASH */
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
const struct nls_table * nls_cp)
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{
int rc = 0;
int len;
char nt_hash[16];
struct HMACMD5Context * pctxt;
wchar_t * user;
wchar_t * domain;
struct HMACMD5Context *pctxt;
wchar_t *user;
wchar_t *domain;
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
if(pctxt == NULL)
if (pctxt == NULL)
return -ENOMEM;
/* calculate md4 hash of password */
......@@ -331,41 +343,45 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
/* convert ses->userName to unicode and uppercase */
len = strlen(ses->userName);
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if(user == NULL)
if (user == NULL)
goto calc_exit_2;
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt);
/* convert ses->domainName to unicode and uppercase */
if(ses->domainName) {
if (ses->domainName) {
len = strlen(ses->domainName);
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if(domain == NULL)
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL)
goto calc_exit_1;
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
UniStrupr(domain);
/* the following line was removed since it didn't work well
with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */
/* UniStrupr(domain); */
hmac_md5_update((char *)domain, 2*len, pctxt);
kfree(domain);
}
calc_exit_1:
kfree(user);
calc_exit_2:
/* BB FIXME what about bytes 24 through 40 of the signing key?
/* BB FIXME what about bytes 24 through 40 of the signing key?
compare with the NTLM example */
hmac_md5_final(ses->server->mac_signing_key, pctxt);
hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
return rc;
}
void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
const struct nls_table * nls_cp)
void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
const struct nls_table *nls_cp)
{
int rc;
struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
struct HMACMD5Context context;
buf->blob_signature = cpu_to_le32(0x00000101);
buf->reserved = 0;
......@@ -379,21 +395,31 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
/* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp);
if(rc)
cERROR(1,("could not get v2 hash rc %d",rc));
if (rc)
cERROR(1, ("could not get v2 hash rc %d", rc));
CalcNTLMv2_response(ses, resp_buf);
/* now calculate the MAC key for NTLMv2 */
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
hmac_md5_update(resp_buf, 16, &context);
hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
sizeof(struct ntlmv2_resp));
ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
}
void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
void CalcNTLMv2_response(const struct cifsSesInfo *ses,
char *v2_session_response)
{
struct HMACMD5Context context;
/* rest of v2 struct already generated */
memcpy(v2_session_response + 8, ses->server->cryptKey,8);
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
hmac_md5_update(v2_session_response+8,
hmac_md5_update(v2_session_response+8,
sizeof(struct ntlmv2_resp) - 8, &context);
hmac_md5_final(v2_session_response,&context);
hmac_md5_final(v2_session_response, &context);
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
}
此差异已折叠。
......@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CIFSFS_H
......@@ -43,9 +43,9 @@ extern void cifs_read_inode(struct inode *);
/* Functions related to inodes */
extern const struct inode_operations cifs_dir_inode_ops;
extern int cifs_create(struct inode *, struct dentry *, int,
extern int cifs_create(struct inode *, struct dentry *, int,
struct nameidata *);
extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
......@@ -63,16 +63,16 @@ extern const struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
extern const struct file_operations cifs_file_ops;
extern const struct file_operations cifs_file_direct_ops; /* if directio mount */
extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
extern const struct file_operations cifs_file_nobrl_ops;
extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
size_t read_size, loff_t * poffset);
size_t read_size, loff_t *poffset);
extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
size_t write_size, loff_t * poffset);
size_t write_size, loff_t *poffset);
extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_flush(struct file *, fl_owner_t id);
......@@ -88,8 +88,9 @@ extern struct dentry_operations cifs_ci_dentry_ops;
/* Functions related to symlinks */
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
extern void cifs_put_link(struct dentry *direntry,
struct nameidata *nd, void *);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
......@@ -98,7 +99,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
extern int cifs_ioctl (struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.49"
#define CIFS_VERSION "1.50"
#endif /* _CIFSFS_H */
/*
* fs/cifs/cifsglob.h
*
* Copyright (C) International Business Machines Corp., 2002,2006
* Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
......@@ -14,7 +14,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details.
*
*
*/
#include <linux/in.h>
#include <linux/in6.h>
......@@ -28,7 +28,7 @@
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
#define MAX_SERVER_SIZE 15
#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
termination then *2 for unicode versions */
#define MAX_PASSWORD_SIZE 16
......@@ -38,13 +38,13 @@
/*
* MAX_REQ is the maximum number of requests that WE will send
* on one socket concurently. It also matches the most common
* value of max multiplex returned by servers. We may
* value of max multiplex returned by servers. We may
* eventually want to use the negotiated value (in case
* future servers can handle more) when we are more confident that
* we will not have problems oveloading the socket with pending
* write data.
*/
#define CIFS_MAX_REQ 50
#define CIFS_MAX_REQ 50
#define SERVER_NAME_LENGTH 15
#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
......@@ -104,6 +104,17 @@ enum protocolEnum {
/* Netbios frames protocol not supported at this time */
};
struct mac_key {
unsigned int len;
union {
char ntlm[CIFS_SESS_KEY_SIZE + 16];
struct {
char key[16];
struct ntlmv2_resp resp;
} ntlmv2;
} data;
};
/*
*****************************************************************
* Except the CIFS PDUs themselves all the
......@@ -120,13 +131,13 @@ struct TCP_Server_Info {
struct sockaddr_in sockAddr;
struct sockaddr_in6 sockAddr6;
} addr;
wait_queue_head_t response_q;
wait_queue_head_t response_q;
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
struct list_head pending_mid_q;
void *Server_NlsInfo; /* BB - placeholder for future NLS info */
unsigned short server_codepage; /* codepage for the server */
unsigned long ip_address; /* IP addr for the server if known */
enum protocolEnum protocolType;
enum protocolEnum protocolType;
char versionMajor;
char versionMinor;
unsigned svlocal:1; /* local server or remote */
......@@ -159,14 +170,15 @@ struct TCP_Server_Info {
/* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
__u32 sequence_number; /* needed for CIFS PDU signature */
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
struct mac_key mac_signing_key;
char ntlmv2_hash[16];
unsigned long lstrp; /* when we got last response from this server */
};
/*
* The following is our shortcut to user information. We surface the uid,
* and name. We always get the password on the fly in case it
* has changed. We also hang a list of sessions owned by this user off here.
* has changed. We also hang a list of sessions owned by this user off here.
*/
struct cifsUidInfo {
struct list_head userList;
......@@ -197,11 +209,11 @@ struct cifsSesInfo {
int Suid; /* remote smb uid */
uid_t linux_uid; /* local Linux uid */
int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
char userName[MAX_USERNAME_SIZE + 1];
char * domainName;
char * password;
char *domainName;
char *password;
};
/* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1
......@@ -213,7 +225,7 @@ struct cifsSesInfo {
#define CIFS_SES_LANMAN 8
/*
* there is one of these for each connection to a resource on a particular
* session
* session
*/
struct cifsTconInfo {
struct list_head cifsConnectionList;
......@@ -269,7 +281,9 @@ struct cifsTconInfo {
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
unsigned retry:1;
unsigned nocase:1;
/* BB add field for back pointer to sb struct? */
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
for this mount even if server would support */
/* BB add field for back pointer to sb struct(s)? */
};
/*
......@@ -291,9 +305,9 @@ struct cifs_search_info {
__u16 entries_in_buffer;
__u16 info_level;
__u32 resume_key;
char * ntwrk_buf_start;
char * srch_entries_start;
char * presume_name;
char *ntwrk_buf_start;
char *srch_entries_start;
char *presume_name;
unsigned int resume_name_len;
unsigned endOfSearch:1;
unsigned emptyDir:1;
......@@ -309,15 +323,15 @@ struct cifsFileInfo {
__u16 netfid; /* file id from remote */
/* BB add lock scope info here if needed */ ;
/* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
struct file *pfile; /* needed for writepage */
struct inode *pInode; /* needed for oplock break */
struct mutex lock_mutex;
struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
atomic_t wrtPending; /* handle in use - defer close */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char * search_resume_name; /* BB removeme BB */
char *search_resume_name; /* BB removeme BB */
struct cifs_search_info srch_inf;
};
......@@ -327,7 +341,7 @@ struct cifsFileInfo {
struct cifsInodeInfo {
struct list_head lockList;
/* BB add in lists for dirty pages - i.e. write caching info for oplock */
/* BB add in lists for dirty pages i.e. write caching info for oplock */
struct list_head openFileList;
int write_behind_rc;
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
......@@ -381,9 +395,9 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
}
#else
#define cifs_stats_inc(field) do {} while(0)
#define cifs_stats_bytes_written(tcon, bytes) do {} while(0)
#define cifs_stats_bytes_read(tcon, bytes) do {} while(0)
#define cifs_stats_inc(field) do {} while (0)
#define cifs_stats_bytes_written(tcon, bytes) do {} while (0)
#define cifs_stats_bytes_read(tcon, bytes) do {} while (0)
#endif
......@@ -410,8 +424,8 @@ struct mid_q_entry {
struct oplock_q_entry {
struct list_head qhead;
struct inode * pinode;
struct cifsTconInfo * tcon;
struct inode *pinode;
struct cifsTconInfo *tcon;
__u16 netfid;
};
......@@ -426,7 +440,7 @@ struct dir_notify_req {
__u16 netfid;
__u32 filter; /* CompletionFilter (for multishot) */
int multishot;
struct file * pfile;
struct file *pfile;
};
#define MID_FREE 0
......@@ -464,7 +478,7 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
#else
#else
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
......@@ -502,7 +516,7 @@ require use of the stronger protocol */
* ----------
* sesSem operations on smb session
* tconSem operations on tree connection
* fh_sem file handle reconnection operations
* fh_sem file handle reconnection operations
*
****************************************************************************/
......@@ -515,7 +529,7 @@ require use of the stronger protocol */
/*
* The list of servers that did not respond with NT LM 0.12.
* This list helps improve performance and eliminate the messages indicating
* that we had a communications error talking to the server in this list.
* that we had a communications error talking to the server in this list.
*/
/* Feature not supported */
/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
......@@ -568,12 +582,12 @@ GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */
GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
to be established on existing mount if we
have the uid/password or Kerberos credential
have the uid/password or Kerberos credential
or equivalent for current user */
GLOBAL_EXTERN unsigned int oplockEnabled;
GLOBAL_EXTERN unsigned int experimEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled;
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
......
此差异已折叠。
......@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CIFSPROTO_H
#define _CIFSPROTO_H
......@@ -49,9 +49,9 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* out */ ,
int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op);
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ ,
......@@ -64,19 +64,19 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType);
extern int cifs_inet_pton(int, char * source, void *dst);
extern int cifs_inet_pton(int, char *source, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */);
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses,
void ** request_buf);
void **request_buf);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage,
const int stage,
const struct nls_table *nls_cp);
extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
......@@ -85,12 +85,12 @@ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
const unsigned char *search_path,
FILE_ALL_INFO * pfile_info,
struct super_block *sb, int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb,int xid);
struct super_block *sb, int xid);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
......@@ -98,8 +98,8 @@ extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
void cifs_proc_init(void);
void cifs_proc_clean(void);
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table *nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
......@@ -108,11 +108,11 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName, const struct nls_table *nls_codepage,
__u16 *searchHandle, struct cifs_search_info * psrch_inf,
__u16 *searchHandle, struct cifs_search_info *psrch_inf,
int map, const char dirsep);
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
__u16 searchHandle, struct cifs_search_info * psrch_inf);
__u16 searchHandle, struct cifs_search_info *psrch_inf);
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
const __u16 search_handle);
......@@ -123,9 +123,9 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
int legacy /* whether to use old info level */,
const struct nls_table *nls_codepage, int remap);
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_ALL_INFO * findData,
const struct nls_table *nls_codepage, int remap);
const unsigned char *searchName,
FILE_ALL_INFO *findData,
const struct nls_table *nls_codepage, int remap);
extern int CIFSSMBUnixQPathInfo(const int xid,
struct cifsTconInfo *tcon,
......@@ -143,13 +143,13 @@ extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path,
const struct nls_table *nls_codepage, int remap);
extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path,
const char *old_path,
const struct nls_table *nls_codepage,
unsigned int *pnum_referrals,
unsigned char ** preferrals,
unsigned int *pnum_referrals,
unsigned char **preferrals,
int remap);
extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
struct super_block * sb, struct smb_vol * vol);
struct super_block *sb, struct smb_vol *vol);
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct kstatfs *FSData);
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
......@@ -181,11 +181,11 @@ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle,__u32 opener_pid,
__u64 size, __u16 fileHandle, __u32 opener_pid,
int AllocSizeFlag);
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid,
__u64 gid, dev_t dev,
__u64 gid, dev_t dev,
const struct nls_table *nls_codepage,
int remap_special_chars);
......@@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
const char *name, const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
const char *name, __u16 type,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
const char *name,
const struct nls_table *nls_codepage,
......@@ -205,8 +208,8 @@ extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int netfid, char * target_name,
extern int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
int netfid, char *target_name,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSCreateHardLink(const int xid,
......@@ -217,7 +220,7 @@ extern int CIFSCreateHardLink(const int xid,
extern int CIFSUnixCreateHardLink(const int xid,
struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSUnixCreateSymLink(const int xid,
struct cifsTconInfo *tcon,
......@@ -228,7 +231,7 @@ extern int CIFSSMBUnixQuerySymLink(const int xid,
const unsigned char *searchName,
char *syminfo, const int buflen,
const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *symlinkinfo, const int buflen, __u16 fid,
......@@ -244,35 +247,35 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage, int remap);
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
u32 posix_flags, __u64 mode, __u16 * netfid,
FILE_UNIX_BASIC_INFO *pRetData,
__u32 *pOplock, const char *name,
const struct nls_table *nls_codepage, int remap);
const struct nls_table *nls_codepage, int remap);
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id);
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
const int netfid, unsigned int count,
const __u64 lseek, unsigned int *nbytes, char **buf,
int * return_buf_type);
const int netfid, unsigned int count,
const __u64 lseek, unsigned int *nbytes, char **buf,
int *return_buf_type);
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes,
const char *buf, const char __user *ubuf,
const char *buf, const char __user *ubuf,
const int long_op);
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes,
const __u64 offset, unsigned int *nbytes,
struct kvec *iov, const int nvec, const int long_op);
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 * inode_number,
const struct nls_table *nls_codepage,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
const struct nls_table * codepage);
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
const struct nls_table * cp, int mapChars);
const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u64 len,
......@@ -281,7 +284,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const int waitFlag);
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag,
const __u64 len, struct file_lock *,
const __u64 len, struct file_lock *,
const __u16 lock_type, const int waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
......@@ -291,54 +294,56 @@ extern void sesInfoFree(struct cifsSesInfo *);
extern struct cifsTconInfo *tconInfoAlloc(void);
extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
__u32 *);
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
extern int cifs_verify_signature(struct smb_hdr *,
const struct mac_key *mac_key,
__u32 expected_sequence_number);
extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
const char *fromName,
const __u16 target_tid,
const char *toName, const int flags,
const struct nls_table *nls_codepage,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid,
__u32 filter, struct file * file, int multishot,
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs, const __u16 netfid,
__u32 filter, struct file *file, int multishot,
const struct nls_table *nls_codepage);
extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, char * EAData,
const unsigned char *searchName, char *EAData,
size_t bufsize, const struct nls_table *nls_codepage,
int remap_special_chars);
extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
const unsigned char * searchName,const unsigned char * ea_name,
unsigned char * ea_value, size_t buf_size,
extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, const unsigned char *ea_name,
unsigned char *ea_value, size_t buf_size,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const char * ea_name,
const void * ea_value, const __u16 ea_value_len,
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const char *ea_name,
const void *ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
__u16 fid, char *acl_inf, const int buflen,
const int acl_type /* ACCESS vs. DEFAULT */);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,const int acl_type,
char *acl_inf, const int buflen, const int acl_type,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *fileName,
const char *local_acl, const int buflen, const int acl_type,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
#endif /* _CIFSPROTO_H */
此差异已折叠。
此差异已折叠。
......@@ -135,10 +135,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
FILE_ALL_INFO * buf = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode;
struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo *pCifsInode;
int disposition = FILE_OVERWRITE_IF;
int write_only = FALSE;
......@@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
} else {
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(oplock & CIFS_CREATE_ACTION)) {
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
......@@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
/* Could set r/o dos attribute if mode & 0222 == 0 */
}
/* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX)
/* server might mask mode so we have to query for it */
if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid);
else {
......@@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
if ((nd->flags & LOOKUP_OPEN) == FALSE) {
if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
((nd->flags & LOOKUP_OPEN) == FALSE)) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle);
} else if (newinode) {
......@@ -323,7 +323,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
struct inode * newinode = NULL;
struct inode *newinode = NULL;
if (!old_valid_dev(device_number))
return -EINVAL;
......@@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry);
if (full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
else if (pTcon->unix_ext) {
mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
......@@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
cFYI(1,
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
if (pTcon->ses->capabilities & CAP_UNIX)
if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb, xid);
else
......
......@@ -5,7 +5,7 @@
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Common Internet FileSystem (CIFS) client
*
*
* Operations related to support for exporting files via NFSD
*
* This library is free software; you can redistribute it and/or modify
......@@ -22,32 +22,45 @@
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
/*
* See Documentation/filesystems/Exporting
* and examples in fs/exportfs
*
* Since cifs is a network file system, an "fsid" must be included for
* any nfs exports file entries which refer to cifs paths. In addition
* the cifs mount must be mounted with the "serverino" option (ie use stable
* server inode numbers instead of locally generated temporary ones).
* Although cifs inodes do not use generation numbers (have generation number
* of zero) - the inode number alone should be good enough for simple cases
* in which users want to export cifs shares with NFS. The decode and encode
* could be improved by using a new routine which expects 64 bit inode numbers
* instead of the default 32 bit routines in fs/exportfs
*
*/
#include <linux/fs.h>
#include <linux/exportfs.h>
#include "cifsglob.h"
#include "cifs_debug.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry)
{
/* BB need to add code here eventually to enable export via NFSD */
return ERR_PTR(-EACCES);
/* BB need to add code here eventually to enable export via NFSD */
cFYI(1, ("get parent for %p", dentry));
return ERR_PTR(-EACCES);
}
struct export_operations cifs_export_ops = {
.get_parent = cifs_get_parent,
/* Following five export operations are unneeded so far and can default */
/* .get_dentry =
.get_name =
.find_exported_dentry =
.decode_fh =
.encode_fs = */
};
.get_parent = cifs_get_parent,
/* Following five export operations are unneeded so far and can default:
.get_dentry =
.get_name =
.find_exported_dentry =
.decode_fh =
.encode_fs = */
};
#endif /* EXPERIMENTAL */
......@@ -66,7 +66,7 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
return cifs_ntfy_flags;
}
int cifs_dir_notify(struct file * file, unsigned long arg)
int cifs_dir_notify(struct file *file, unsigned long arg)
{
int xid;
int rc = -EINVAL;
......
此差异已折叠。
此差异已折叠。
......@@ -3,7 +3,7 @@
*
* vfs operations that deal with io control
*
* Copyright (C) International Business Machines Corp., 2005
* Copyright (C) International Business Machines Corp., 2005,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
......@@ -30,7 +30,7 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
int cifs_ioctl (struct inode * inode, struct file * filep,
int cifs_ioctl (struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg)
{
int rc = -ENOTTY; /* strange error - but the precedent */
......
......@@ -50,32 +50,33 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry);
if((fromName == NULL) || (toName == NULL)) {
if ((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
}
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
if (pTcon->unix_ext)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls,
cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
else {
rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls,
cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP;
if ((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP;
}
d_drop(direntry); /* force new lookup from server of target */
/* if source file is cached (oplocked) revalidate will not go to server
until the file is closed or oplock broken so update nlinks locally */
if(old_file->d_inode) {
if (old_file->d_inode) {
cifsInode = CIFS_I(old_file->d_inode);
if(rc == 0) {
if (rc == 0) {
old_file->d_inode->i_nlink++;
/* BB should we make this contingent on superblock flag NOATIME? */
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
......@@ -84,14 +85,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
to set the parent dir cifs inode time to zero
to force revalidate (faster) for it too? */
}
/* if not oplocked will force revalidate to get info
/* if not oplocked will force revalidate to get info
on source file from srv */
cifsInode->time = 0;
/* Will update parent dir timestamps from srv within a second.
/* Will update parent dir timestamps from srv within a second.
Would it really be worth it to set the parent dir (cifs
inode) time field to zero to force revalidate on parent
directory faster ie
directory faster ie
CIFS_I(inode)->time = 0; */
}
......@@ -109,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
int rc = -EACCES;
int xid;
char *full_path = NULL;
char * target_path = ERR_PTR(-ENOMEM);
char *target_path = ERR_PTR(-ENOMEM);
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
......@@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
goto out;
}
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
/* We could change this to:
if (pTcon->unix_ext)
but there does not seem any point in refusing to
get symlink info if we can, even if unix extensions
turned off for this mount */
if (pTcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
target_path,
PATH_MAX-1,
cifs_sb->local_nls);
else {
/* BB add read reparse point symlink code here */
/* rc = CIFSSMBQueryReparseLinkInfo */
/* BB Add code to Query ReparsePoint info */
/* BB Add MAC style xsymlink check here if enabled */
......@@ -176,7 +183,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
......@@ -185,19 +192,20 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cFYI(1, ("symname is %s", symname));
/* BB what if DFS and this volume is on different share? BB */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
if (pTcon->unix_ext)
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
cifs_sb->local_nls);
/* else
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls); */
if (rc == 0) {
if (pTcon->ses->capabilities & CAP_UNIX)
if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid);
inode->i_sb, xid);
else
rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb,xid);
inode->i_sb, xid);
if (rc != 0) {
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
......@@ -226,9 +234,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
char *tmp_path = NULL;
char * tmpbuffer;
unsigned char * referrals = NULL;
char *tmp_path = NULL;
char *tmpbuffer;
unsigned char *referrals = NULL;
int num_referrals = 0;
int len;
__u16 fid;
......@@ -237,13 +245,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
/* BB would it be safe against deadlock to grab this sem
/* BB would it be safe against deadlock to grab this sem
even though rename itself grabs the sem and calls lookup? */
/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
full_path = build_path_from_dentry(direntry);
/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
if(full_path == NULL) {
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
......@@ -251,70 +259,80 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
cFYI(1,
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen));
if(buflen > PATH_MAX)
if (buflen > PATH_MAX)
len = PATH_MAX;
else
len = buflen;
tmpbuffer = kmalloc(len,GFP_KERNEL);
if(tmpbuffer == NULL) {
tmpbuffer = kmalloc(len, GFP_KERNEL);
if (tmpbuffer == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
/* BB add read reparse point symlink code and
Unix extensions symlink code here BB */
/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
tmpbuffer,
len - 1,
cifs_sb->local_nls);
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
cERROR(1,("SFU style symlinks not implemented yet"));
cERROR(1, ("SFU style symlinks not implemented yet"));
/* add open and read as in fs/cifs/inode.c */
} else {
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
OPEN_REPARSE_POINT,&fid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if(!rc) {
if (!rc) {
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
tmpbuffer,
len - 1,
len - 1,
fid,
cifs_sb->local_nls);
if(CIFSSMBClose(xid, pTcon, fid)) {
cFYI(1,("Error closing junction point (open for ioctl)"));
if (CIFSSMBClose(xid, pTcon, fid)) {
cFYI(1, ("Error closing junction point "
"(open for ioctl)"));
}
if(rc == -EIO) {
if (rc == -EIO) {
/* Query if DFS Junction */
tmp_path =
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
GFP_KERNEL);
if (tmp_path) {
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
strncat(tmp_path, full_path, MAX_PATHCONF);
rc = get_dfs_path(xid, pTcon->ses, tmp_path,
strncpy(tmp_path, pTcon->treeName,
MAX_TREE_SIZE);
strncat(tmp_path, full_path,
MAX_PATHCONF);
rc = get_dfs_path(xid, pTcon->ses,
tmp_path,
cifs_sb->local_nls,
&num_referrals, &referrals,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
if((num_referrals == 0) && (rc == 0))
cFYI(1, ("Get DFS for %s rc = %d ",
tmp_path, rc));
if ((num_referrals == 0) && (rc == 0))
rc = -EACCES;
else {
cFYI(1,("num referral: %d",num_referrals));
if(referrals) {
cFYI(1,("referral string: %s",referrals));
strncpy(tmpbuffer, referrals, len-1);
cFYI(1, ("num referral: %d",
num_referrals));
if (referrals) {
cFYI(1,("referral string: %s", referrals));
strncpy(tmpbuffer,
referrals,
len-1);
}
}
kfree(referrals);
kfree(tmp_path);
}
/* BB add code like else decode referrals then memcpy to
tmpbuffer and free referrals string array BB */
/* BB add code like else decode referrals
then memcpy to tmpbuffer and free referrals
string array BB */
}
}
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册