#include <linux/mempool.h>
#include <linux/delay.h>
#include <linux/completion.h>
+#include <linux/pagevec.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include "cifspdu.h"
#include "ntlmssp.h"
#include "nterr.h"
#include "rfc1002pdu.h"
+#include "cn_cifs.h"
#define CIFS_PORT 445
#define RFC1001_PORT 139
unsigned setuids:1;
unsigned noperm:1;
unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+ unsigned cifs_acl:1;
unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
unsigned direct_io:1;
unsigned remap:1; /* set to remap seven reserved chars in filenames */
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
unsigned sfu_emul:1;
+ unsigned krb5:1;
+ unsigned ntlm:1;
+ unsigned ntlmv2:1;
+ unsigned nullauth:1; /* attempt to authenticate with null user */
+ unsigned sign:1;
+ unsigned seal:1; /* encrypt */
unsigned nocase; /* request case insensitive filenames */
unsigned nobrl; /* disable sending byte range locks to srv */
unsigned int rsize;
server->server_RFC1001_name);
}
if(rc) {
+ cFYI(1,("reconnect error %d",rc));
msleep(3000);
} else {
atomic_inc(&tcpSesReconnectCount);
}
while (server->tcpStatus != CifsExiting) {
- if(try_to_freeze())
+ if (try_to_freeze())
continue;
if (bigbuf == NULL) {
bigbuf = cifs_buf_get();
/* else length ok */
reconnect = 0;
- if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
+ if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
isLargeBuf = TRUE;
memcpy(bigbuf, smallbuf, 4);
smb_buffer = bigbuf;
dump_smb(smb_buffer, length);
if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
- cERROR(1, ("Bad SMB Received "));
+ cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
continue;
}
multi_t2_fnd:
task_to_wake = mid_entry->tsk;
mid_entry->midState = MID_RESPONSE_RECEIVED;
+#ifdef CONFIG_CIFS_STATS2
+ mid_entry->when_received = jiffies;
+#endif
break;
}
}
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE;
-
+ vol->ntlm = TRUE;
/* default is always to request posix paths. */
vol->posix_paths = 1;
/* go from value to value + temp_len condensing
double commas to singles. Note that this ends up
allocating a few bytes too many, which is ok */
- vol->password = kcalloc(1, temp_len, GFP_KERNEL);
+ vol->password = kzalloc(temp_len, GFP_KERNEL);
if(vol->password == NULL) {
printk("CIFS: no memory for pass\n");
return 1;
}
vol->password[j] = 0;
} else {
- vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
+ vol->password = kzalloc(temp_len+1, GFP_KERNEL);
if(vol->password == NULL) {
printk("CIFS: no memory for pass\n");
return 1;
printk(KERN_WARNING "CIFS: ip address too long\n");
return 1;
}
+ } else if (strnicmp(data, "sec", 3) == 0) {
+ if (!value || !*value) {
+ cERROR(1,("no security value specified"));
+ continue;
+ } else if (strnicmp(value, "krb5i", 5) == 0) {
+ vol->sign = 1;
+ vol->krb5 = 1;
+ } else if (strnicmp(value, "krb5p", 5) == 0) {
+ /* vol->seal = 1;
+ vol->krb5 = 1; */
+ cERROR(1,("Krb5 cifs privacy not supported"));
+ return 1;
+ } else if (strnicmp(value, "krb5", 4) == 0) {
+ vol->krb5 = 1;
+ } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
+ vol->ntlmv2 = 1;
+ vol->sign = 1;
+ } else if (strnicmp(value, "ntlmv2", 6) == 0) {
+ vol->ntlmv2 = 1;
+ } else if (strnicmp(value, "ntlmi", 5) == 0) {
+ vol->ntlm = 1;
+ vol->sign = 1;
+ } else if (strnicmp(value, "ntlm", 4) == 0) {
+ /* ntlm is default so can be turned off too */
+ vol->ntlm = 1;
+ } else if (strnicmp(value, "nontlm", 6) == 0) {
+ vol->ntlm = 0;
+ } else if (strnicmp(value, "none", 4) == 0) {
+ vol->nullauth = 1;
+ } else {
+ cERROR(1,("bad security option: %s", value));
+ return 1;
+ }
} else if ((strnicmp(data, "unc", 3) == 0)
|| (strnicmp(data, "target", 6) == 0)
|| (strnicmp(data, "path", 4) == 0)) {
vol->server_ino = 1;
} else if (strnicmp(data, "noserverino",9) == 0) {
vol->server_ino = 0;
+ } else if (strnicmp(data, "cifsacl",7) == 0) {
+ vol->cifs_acl = 1;
+ } else if (strnicmp(data, "nocifsacl", 9) == 0) {
+ vol->cifs_acl = 0;
} else if (strnicmp(data, "acl",3) == 0) {
vol->no_psx_acl = 0;
} else if (strnicmp(data, "noacl",5) == 0) {
the helper that resolves tcp names, mount to it, try to
tcon to it unmount it if fail */
- if(referrals)
- kfree(referrals);
+ kfree(referrals);
return rc;
}
/* Eventually check for other socket options to change from
the default. sock_setsockopt not used because it expects
user space buffer */
+ cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
+ (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+ /* make the bufsizes depend on wsize/rsize and max requests */
+ if((*csocket)->sk->sk_sndbuf < (200 * 1024))
+ (*csocket)->sk->sk_sndbuf = 200 * 1024;
+ if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
+ (*csocket)->sk->sk_rcvbuf = 140 * 1024;
/* send RFC1001 sessinit */
-
if(psin_server->sin_port == htons(RFC1001_PORT)) {
/* some servers require RFC1001 sessinit before sending
negprot - BB check reconnection in case where second
sessinit is sent but no second negprot */
struct rfc1002_session_packet * ses_init_buf;
struct smb_hdr * smb_buf;
- ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+ ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
if(ses_init_buf) {
ses_init_buf->trailer.session_req.called_len = 32;
if(target_name && (target_name[0] != 0)) {
memset(&volume_info,0,sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
cFYI(1, ("Username: %s ", volume_info.username));
} else {
- cifserror("No username specified ");
+ cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
if(rc <= 0) {
/* we failed translating address */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
} else if (volume_info.UNCip){
/* BB using ip addr as server name connect to the DFS root below */
cERROR(1,("Connecting to DFS root not implemented yet"));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
} else /* which servers DFS root would we conect to */ {
cERROR(1,
- ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
cifs_sb->local_nls = load_nls(volume_info.iocharset);
if(cifs_sb->local_nls == NULL) {
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -ELIBACC;
}
&sin_server6.sin6_addr,
volume_info.username, &srvTcp);
else {
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
if (srvTcp) {
- cFYI(1, ("Existing tcp session with server found "));
+ cFYI(1, ("Existing tcp session with server found"));
} else { /* create socket */
if(volume_info.port)
sin_server.sin_port = htons(volume_info.port);
("Error connecting to IPv4 socket. Aborting operation"));
if(csocket != NULL)
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
}
if (srvTcp == NULL) {
rc = -ENOMEM;
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
} else {
if(rc < 0) {
rc = -ENOMEM;
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
}
if (existingCifsSes) {
pSesInfo = existingCifsSes;
- cFYI(1, ("Existing smb sess found "));
- if(volume_info.password)
- kfree(volume_info.password);
+ cFYI(1, ("Existing smb sess found"));
+ kfree(volume_info.password);
/* volume_info.UNC freed at end of function */
} else if (!rc) {
- cFYI(1, ("Existing smb sess not found "));
+ cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
if (pSesInfo == NULL)
rc = -ENOMEM;
if(!rc)
atomic_inc(&srvTcp->socketUseCount);
} else
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.password);
}
/* search for existing tcon to this server share */
if (!rc) {
- if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
+ if(volume_info.rsize > CIFSMaxBufSize) {
+ cERROR(1,("rsize %d too large, using MaxBufSize",
+ volume_info.rsize));
+ cifs_sb->rsize = CIFSMaxBufSize;
+ } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
cifs_sb->rsize = volume_info.rsize;
- else
- cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
- if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
+ else /* default */
+ cifs_sb->rsize = CIFSMaxBufSize;
+
+ if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+ cERROR(1,("wsize %d too large using 4096 instead",
+ volume_info.wsize));
+ cifs_sb->wsize = 4096;
+ } else if(volume_info.wsize)
cifs_sb->wsize = volume_info.wsize;
else
- cifs_sb->wsize = CIFSMaxBufSize; /* default */
+ cifs_sb->wsize =
+ min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+ 127*1024);
+ /* old default of CIFSMaxBufSize was too small now
+ that SMB Write2 can send multiple pages in kvec.
+ RFC1001 does not describe what happens when frame
+ bigger than 128K is sent so use that as max in
+ conjunction with 52K kvec constraint on arch with 4K
+ page size */
+
if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
cifs_sb->rsize = PAGE_CACHE_SIZE;
/* Windows ME does this */
cifs_sb->mnt_gid = volume_info.linux_gid;
cifs_sb->mnt_file_mode = volume_info.file_mode;
cifs_sb->mnt_dir_mode = volume_info.dir_mode;
- cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+ cFYI(1,("file mode: 0x%x dir mode: 0x%x",
+ cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
if(volume_info.noperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
if(volume_info.nobrl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+ if(volume_info.cifs_acl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
if(volume_info.direct_io) {
cFYI(1,("mounting share using direct i/o"));
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
volume_info.username);
if (tcon) {
- cFYI(1, ("Found match on UNC path "));
+ cFYI(1, ("Found match on UNC path"));
/* we can have only one retry value for a connection
to a share so for resources mounted more than once
to the same server share the last value passed in
"", cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
+ kfree(volume_info.UNC);
FreeXid(xid);
return -ENODEV;
} else {
}
}
}
+ if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
+ cifs_sb->wsize = min(cifs_sb->wsize,
+ (tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE));
+ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
+ cifs_sb->rsize = min(cifs_sb->rsize,
+ (tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE));
}
/* volume_info.password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created
the password ptr is put in the new session structure (in which case the
password will be freed at unmount time) */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
+ kfree(volume_info.UNC);
FreeXid(xid);
return rc;
}
__u32 capabilities;
__u16 count;
- cFYI(1, ("In sesssetup "));
+ cFYI(1, ("In sesssetup"));
if(ses == NULL)
return -EINVAL;
user = ses->userName;
bytes_returned = 0; /* skill null user */
else
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
+ cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
nls_codepage);
/* convert number of 16 bit words to bytes */
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* trailing null */
if (domain == NULL)
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr,
+ cifs_strtoUCS((__le16 *) bcc_ptr,
"CIFS_LINUX_DOM", 32, nls_codepage);
else
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
+ cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
- ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverOS,
- (wchar_t *)bcc_ptr, len,nls_codepage);
+ (__le16 *)bcc_ptr, len,nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words -= len + 1;
ses->serverOS[2 * len] = 0;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *)bcc_ptr,
remaining_words-1);
- ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
+ ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverNOS,
- (wchar_t *)bcc_ptr,len,nls_codepage);
+ (__le16 *)bcc_ptr,len,nls_codepage);
bcc_ptr += 2 * (len + 1);
ses->serverNOS[2 * len] = 0;
ses->serverNOS[1 + (2 * len)] = 0;
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2*(len+1),GFP_KERNEL);
+ kzalloc(2*(len+1),GFP_KERNEL);
if(ses->serverDomain == NULL)
goto sesssetup_nomem;
cifs_strfromUCS_le(ses->serverDomain,
- (wchar_t *)bcc_ptr,len,nls_codepage);
+ (__le16 *)bcc_ptr,len,nls_codepage);
bcc_ptr += 2 * (len + 1);
ses->serverDomain[2*len] = 0;
ses->serverDomain[1+(2*len)] = 0;
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
/* if these kcallocs fail not much we
can do, but better to not fail the
sesssetup itself */
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
ses->serverNOS =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverDomain == NULL)
goto sesssetup_nomem;
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr++;
}
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
+ cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
bcc_ptr += 2; /* trailing null */
if (domain == NULL)
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr,
+ cifs_strtoUCS((__le16 *) bcc_ptr,
"CIFS_LINUX_DOM", 32, nls_codepage);
else
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+ cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
- (wchar_t *)
+ (__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->serverNOS,
- (wchar_t *)bcc_ptr,
+ (__le16 *)bcc_ptr,
len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
- ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
+ ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
cifs_strfromUCS_le(ses->serverDomain,
- (wchar_t *)bcc_ptr,
- len,
- nls_codepage);
+ (__le16 *)bcc_ptr,
+ len, nls_codepage);
bcc_ptr += 2*(len+1);
ses->serverDomain[2*len] = 0;
ses->serverDomain[1+(2*len)] = 0;
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2,GFP_KERNEL);
+ kzalloc(2,GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
- ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
- ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+ ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
+ ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
__u32 negotiate_flags, capabilities;
__u16 count;
- cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+ cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
if(ses == NULL)
return -EINVAL;
domain = ses->domainName;
SecurityBlob->MessageType = NtLmNegotiate;
negotiate_flags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
- NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_56 |
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
if(sign_CIFS_PDUs)
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
SecurityBlob->WorkstationName.Length = 0;
SecurityBlob->WorkstationName.MaximumLength = 0;
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 len;
- negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
- strncpy(bcc_ptr, domain, 63);
- len = strnlen(domain, 64);
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(len);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32((long) &SecurityBlob->
- DomainString -
- (long) &SecurityBlob->Signature);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->DomainName.Length =
- cpu_to_le16(len);
- }
+ /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
+ along with username on auth request (ie the response to challenge) */
+ SecurityBlob->DomainName.Buffer = 0;
+ SecurityBlob->DomainName.Length = 0;
+ SecurityBlob->DomainName.MaximumLength = 0;
if (ses->capabilities & CAP_UNICODE) {
if ((long) bcc_ptr % 2) {
*bcc_ptr = 0;
}
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+ cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* null terminate Linux version */
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
*(bcc_ptr + 1) = 0;
SecurityBlob2->MessageType));
} else if (ses) {
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
- cFYI(1, ("UID = %d ", ses->Suid));
+ cFYI(1, ("UID = %d", ses->Suid));
if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4)
&& (blob_len <
if (pSMBr->resp.hdr.WordCount == 4) {
bcc_ptr += blob_len;
- cFYI(1,
- ("Security Blob Length %d ",
+ cFYI(1, ("Security Blob Length %d",
blob_len));
}
- cFYI(1, ("NTLMSSP Challenge rcvd "));
+ cFYI(1, ("NTLMSSP Challenge rcvd"));
memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE);
- if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
+ if(SecurityBlob2->NegotiateFlags &
+ cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags &
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
- (wchar_t *)
+ (__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
- (wchar_t *)
+ (__le16 *)
bcc_ptr,
len,
nls_codepage);
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2 *
+ kzalloc(2 *
(len +
1),
GFP_KERNEL);
cifs_strfromUCS_le
- (ses->
- serverDomain,
- (wchar_t *)
- bcc_ptr, len,
- nls_codepage);
+ (ses->serverDomain,
+ (__le16 *)bcc_ptr,
+ len, nls_codepage);
bcc_ptr +=
2 * (len + 1);
- ses->
- serverDomain[2
- * len]
+ ses->serverDomain[2*len]
= 0;
- ses->
- serverDomain[1
- +
- (2
- *
- len)]
+ ses->serverDomain
+ [1 + (2 * len)]
= 0;
} /* else no more room so create dummy domain string */
else
ses->serverDomain =
- kcalloc(1, 2,
+ kzalloc(2,
GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
ses->serverDomain =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
ses->serverNOS =
- kcalloc(1, 2, GFP_KERNEL);
+ kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
ses->serverOS =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverOS,
bcc_ptr, len);
len = strnlen(bcc_ptr, 1024);
ses->serverNOS =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
len = strnlen(bcc_ptr, 1024);
ses->serverDomain =
- kcalloc(1, len + 1,
+ kzalloc(len + 1,
GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr++;
} else
cFYI(1,
- ("Variable field of length %d extends beyond end of smb ",
+ ("Variable field of length %d extends beyond end of smb",
len));
}
} else {
SecurityBlob->DomainName.MaximumLength = 0;
} else {
__u16 len =
- cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
nls_codepage);
len *= 2;
SecurityBlob->DomainName.MaximumLength =
SecurityBlob->UserName.MaximumLength = 0;
} else {
__u16 len =
- cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
+ cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
nls_codepage);
len *= 2;
SecurityBlob->UserName.MaximumLength =
cpu_to_le16(len);
}
- /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
+ /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
SecurityBlob->WorkstationName.Length *= 2;
SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
bcc_ptr++;
}
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+ cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* null term version string */
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
64, nls_codepage);
bcc_ptr += 2 * bytes_returned;
*(bcc_ptr + 1) = 0;
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
ses->serverOS =
- kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+ kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
- (wchar_t *)
+ (__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr += 2 * (len + 1);
remaining_words
- 1);
ses->serverNOS =
- kcalloc(1, 2 * (len + 1),
+ kzalloc(2 * (len + 1),
GFP_KERNEL);
cifs_strfromUCS_le(ses->
serverNOS,
- (wchar_t *)
+ (__le16 *)
bcc_ptr,
len,
nls_codepage);
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string not always null terminated (e.g. for Windows XP & 2000) */
ses->serverDomain =
- kcalloc(1, 2 *
+ kzalloc(2 *
(len +
1),
GFP_KERNEL);
cifs_strfromUCS_le
(ses->
serverDomain,
- (wchar_t *)
+ (__le16 *)
bcc_ptr, len,
nls_codepage);
bcc_ptr +=
= 0;
} /* else no more room so create dummy domain string */
else
- ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
+ ses->serverDomain = kzalloc(2,GFP_KERNEL);
} else { /* no room so create dummy domain and NOS string */
- ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
- ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
+ ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
len = strnlen(bcc_ptr, 1024);
if (((long) bcc_ptr + len) -
(long) pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
- ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+ ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len);
bcc_ptr += len;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
+ ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
- ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
+ ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
bcc_ptr[0] = 0;
pSMB->AndXCommand = 0xFF;
pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
- pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
bcc_ptr = &pSMB->Password[0];
- bcc_ptr++; /* skip password */
+ if((ses->server->secMode) & SECMODE_USER) {
+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
+ bcc_ptr++; /* skip password */
+ } else {
+ pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ /* BB FIXME add code to fail this if NTLMv2 or Kerberos
+ specified as required (when that support is added to
+ the vfs in the future) as only NTLM or the much
+ weaker LANMAN (which we do not send) is accepted
+ by Samba (not sure whether other servers allow
+ NTLMv2 password here) */
+ SMBNTencrypt(ses->password,
+ ses->server->cryptKey,
+ bcc_ptr);
+
+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
+ *bcc_ptr = 0;
+ bcc_ptr++; /* align */
+ }
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
length =
- cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
+ cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
bcc_ptr += 2; /* skip trailing null */
} else { /* ASCII */
-
strcpy(bcc_ptr, tree);
bcc_ptr += strlen(tree) + 1;
}
if ((bcc_ptr + (2 * length)) -
pByteArea(smb_buffer_response) <=
BCC(smb_buffer_response)) {
- if(tcon->nativeFileSystem)
- kfree(tcon->nativeFileSystem);
+ kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
- kcalloc(1, length + 2, GFP_KERNEL);
+ kzalloc(length + 2, GFP_KERNEL);
cifs_strfromUCS_le(tcon->nativeFileSystem,
- (wchar_t *) bcc_ptr,
+ (__le16 *) bcc_ptr,
length, nls_codepage);
bcc_ptr += 2 * length;
bcc_ptr[0] = 0; /* null terminate the string */
if ((bcc_ptr + length) -
pByteArea(smb_buffer_response) <=
BCC(smb_buffer_response)) {
- if(tcon->nativeFileSystem)
- kfree(tcon->nativeFileSystem);
+ kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
- kcalloc(1, length + 1, GFP_KERNEL);
+ kzalloc(length + 1, GFP_KERNEL);
strncpy(tcon->nativeFileSystem, bcc_ptr,
length);
}
}
cifs_sb->tcon = NULL;
- if (ses) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 2);
- }
+ if (ses)
+ schedule_timeout_interruptible(msecs_to_jiffies(500));
if (ses)
sesInfoFree(ses);