The Samba-Bugzilla – Attachment 3947 Details for
Bug 6004
Can't mount the same Windows 2003 Server share twice with different users
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch to alter how cifs sends the vcnumber now also handles reconnect
vc-number-fix.patch (text/plain), 7.64 KB, created by
Steve French
on 2009-02-19 23:41:11 UTC
(
hide
)
Description:
patch to alter how cifs sends the vcnumber now also handles reconnect
Filename:
MIME Type:
Creator:
Steve French
Created:
2009-02-19 23:41:11 UTC
Size:
7.64 KB
patch
obsolete
>diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES >index 72063f5..851388f 100644 >--- a/fs/cifs/CHANGES >+++ b/fs/cifs/CHANGES >@@ -1,3 +1,13 @@ >+Version 1.57 >+------------ >+Improve support for multiple security contexts to the same server. We >+used to use the same "vcnumber" for all connections which could cause >+the server to treat subsequent connections, especially those that >+are authenticated as guest, as reconnections, invalidating the earlier >+user's smb session. This fix allows cifs to mount multiple times to the >+same server with different userids without risking invalidating earlier >+established security contexts. >+ > Version 1.56 > ------------ > Add "forcemandatorylock" mount option to allow user to use mandatory >diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h >index 7ac4818..2b1d28a 100644 >--- a/fs/cifs/cifsfs.h >+++ b/fs/cifs/cifsfs.h >@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); > extern const struct export_operations cifs_export_ops; > #endif /* EXPERIMENTAL */ > >-#define CIFS_VERSION "1.56" >+#define CIFS_VERSION "1.57" > #endif /* _CIFSFS_H */ >diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h >index 94c1ca0..e004f6d 100644 >--- a/fs/cifs/cifsglob.h >+++ b/fs/cifs/cifsglob.h >@@ -164,9 +164,12 @@ struct TCP_Server_Info { > /* multiplexed reads or writes */ > unsigned int maxBuf; /* maxBuf specifies the maximum */ > /* message size the server can send or receive for non-raw SMBs */ >- unsigned int maxRw; /* maxRw specifies the maximum */ >+ unsigned int max_rw; /* maxRw specifies the maximum */ > /* message size the server can send or receive for */ > /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ >+ unsigned int max_vcs; /* maximum number of smb sessions, at least >+ those that can be specified uniquely with >+ vcnumbers */ > char sessid[4]; /* unique token id for this session */ > /* (returned on Negotiate */ > int capabilities; /* allow selective disabling of caps by smb sess */ >@@ -210,6 +213,7 @@ struct cifsSesInfo { > unsigned overrideSecFlg; /* if non-zero override global sec flags */ > __u16 ipc_tid; /* special tid for connection to IPC share */ > __u16 flags; >+ __u16 vcnum; > char *serverOS; /* name of operating system underlying server */ > char *serverNOS; /* name of network operating system of server */ > char *serverDomain; /* security realm of server */ >diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c >index 552642a..939e2f7 100644 >--- a/fs/cifs/cifssmb.c >+++ b/fs/cifs/cifssmb.c >@@ -528,14 +528,15 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) > server->maxReq = le16_to_cpu(rsp->MaxMpxCount); > server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), > (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); >+ server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); > GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); > /* even though we do not use raw we might as well set this > accurately, in case we ever find a need for it */ > if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { >- server->maxRw = 0xFF00; >+ server->max_rw = 0xFF00; > server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; > } else { >- server->maxRw = 0;/* we do not need to use raw anyway */ >+ server->max_rw = 0;/* do not need to use raw anyway */ > server->capabilities = CAP_MPX_MODE; > } > tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); >@@ -638,7 +639,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) > /* probably no need to store and check maxvcs */ > server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), > (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); >- server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); >+ server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); > cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); > GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); > server->capabilities = le32_to_cpu(pSMBr->Capabilities); >diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c >index b234407..5c68b42 100644 >--- a/fs/cifs/sess.c >+++ b/fs/cifs/sess.c >@@ -34,15 +34,99 @@ > extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, > unsigned char *p24); > >+/* Checks if this is the first smb session to be reconnected after >+ the socket has been reestablished (so we know whether to use vc 0). >+ Called while holding the cifs_tcp_ses_lock, so do not block */ >+static bool is_first_ses_reconnect(struct cifsSesInfo *ses) >+{ >+ struct list_head *tmp; >+ struct cifsSesInfo *tmp_ses; >+ >+ list_for_each(tmp, &ses->server->smb_ses_list) { >+ tmp_ses = list_entry(tmp, struct cifsSesInfo, >+ smb_ses_list); >+ if (tmp_ses->need_reconnect == false) >+ return false; >+ } >+ /* could not find a session that was already connected, >+ this must be the first one we are reconnecting */ >+ return true; >+} >+ >+/* >+ * vc number 0 is treated specially by some servers, and should be the >+ * first one we request. After that we can use vcnumbers up to maxvcs, >+ * one for each smb session (some Windows versions set maxvcs incorrectly >+ * so maxvc=1 can be ignored). If we have too many vcs, we can reuse >+ * any vc but zero (some servers reset the connection on vcnum zero) >+ * >+ */ >+static __le16 get_next_vcnum(struct cifsSesInfo *ses) >+{ >+ __u16 vcnum = 0; >+ struct list_head *tmp; >+ struct cifsSesInfo *tmp_ses; >+ __u16 max_vcs = ses->server->max_vcs; >+ __u16 i; >+ int free_vc_found = 0; >+ >+ /* Quoting the MS-SMB specification: "Windows-based SMB servers set this >+ field to one but do not enforce this limit, which allows an SMB client >+ to establish more virtual circuits than allowed by this value ... but >+ other server implementations can enforce this limit." */ >+ if (max_vcs < 2) >+ max_vcs = 0xFFFF; >+ >+ write_lock(&cifs_tcp_ses_lock); >+ if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) >+ goto get_vc_num_exit; /* vcnum will be zero */ >+ for (i = ses->server->srv_count - 1; i < max_vcs; i++) { >+ if (i == 0) /* this is the only connection, use vc 0 */ >+ break; >+ >+ free_vc_found = 1; >+ >+ list_for_each(tmp, &ses->server->smb_ses_list) { >+ tmp_ses = list_entry(tmp, struct cifsSesInfo, >+ smb_ses_list); >+ if (tmp_ses->vcnum == i) { >+ free_vc_found = 0; >+ break; /* found duplicate, try next vcnum */ >+ } >+ } >+ if (free_vc_found) >+ break; /* we found a vcnumber that will work - use it */ >+ } >+ >+ if (i == 0) >+ vcnum = 0; /* for most common case, ie if one smb session, use >+ vc zero. Also for case when no free vcnum, zero >+ is safest to send (some clients only send zero) */ >+ else if (free_vc_found == 0) >+ vcnum = 1; /* we can not reuse vc=0 safely, since some servers >+ reset all uids on that, but 1 is ok. */ >+ else >+ vcnum = i; >+ ses->vcnum = vcnum; >+get_vc_num_exit: >+ write_unlock(&cifs_tcp_ses_lock); >+ >+ return le16_to_cpu(vcnum); >+} >+ > static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) > { > __u32 capabilities = 0; > > /* init fields common to all four types of SessSetup */ >- /* note that header is initialized to zero in header_assemble */ >+ /* Note that offsets for first seven fields in req struct are same */ >+ /* in CIFS Specs so does not matter which of 3 forms of struct */ >+ /* that we use in next few lines */ >+ /* Note that header is initialized to zero in header_assemble */ > pSMB->req.AndXCommand = 0xFF; > pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); > pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); >+ pSMB->req.VcNumber = get_next_vcnum(ses); > > /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ > >@@ -71,7 +155,6 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) > if (ses->capabilities & CAP_UNIX) > capabilities |= CAP_UNIX; > >- /* BB check whether to init vcnum BB */ > return capabilities; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 6004
:
3838
|
3839
|
3840
|
3841
|
3895
|
3899
| 3947