4 * Copyright (C) International Business Machines Corp., 2009, 2011
6 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Pavel Shilovsky (pshilovsky@samba.org) 2012
9 * Contains the routines for constructing the SMB2 PDUs themselves
11 * This library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published
13 * by the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
27 /* Note that there are handle based routines which must be */
28 /* treated slightly differently for reconnection purposes since we never */
29 /* want to reuse a stale file handle and only the caller knows the file info */
32 #include <linux/kernel.h>
33 #include <linux/vfs.h>
34 #include <linux/uaccess.h>
35 #include <linux/xattr.h>
39 #include "cifsproto.h"
40 #include "smb2proto.h"
41 #include "cifs_unicode.h"
42 #include "cifs_debug.h"
44 #include "smb2status.h"
47 * The following table defines the expected "StructureSize" of SMB2 requests
48 * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests.
50 * Note that commands are defined in smb2pdu.h in le16 but the array below is
51 * indexed by command in host byte order.
53 static const int smb2_req_struct_sizes
[NUMBER_OF_SMB2_COMMANDS
] = {
54 /* SMB2_NEGOTIATE */ 36,
55 /* SMB2_SESSION_SETUP */ 25,
57 /* SMB2_TREE_CONNECT */ 9,
58 /* SMB2_TREE_DISCONNECT */ 4,
68 /* SMB2_QUERY_DIRECTORY */ 33,
69 /* SMB2_CHANGE_NOTIFY */ 32,
70 /* SMB2_QUERY_INFO */ 41,
71 /* SMB2_SET_INFO */ 33,
72 /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
77 smb2_hdr_assemble(struct smb2_hdr
*hdr
, __le16 smb2_cmd
/* command */ ,
78 const struct cifs_tcon
*tcon
)
80 struct smb2_pdu
*pdu
= (struct smb2_pdu
*)hdr
;
81 char *temp
= (char *)hdr
;
82 /* lookup word count ie StructureSize from table */
83 __u16 parmsize
= smb2_req_struct_sizes
[le16_to_cpu(smb2_cmd
)];
86 * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
87 * largest operations (Create)
91 /* Note this is only network field converted to big endian */
92 hdr
->smb2_buf_length
= cpu_to_be32(parmsize
+ sizeof(struct smb2_hdr
)
93 - 4 /* RFC 1001 length field itself not counted */);
95 hdr
->ProtocolId
[0] = 0xFE;
96 hdr
->ProtocolId
[1] = 'S';
97 hdr
->ProtocolId
[2] = 'M';
98 hdr
->ProtocolId
[3] = 'B';
99 hdr
->StructureSize
= cpu_to_le16(64);
100 hdr
->Command
= smb2_cmd
;
101 hdr
->CreditRequest
= cpu_to_le16(2); /* BB make this dynamic */
102 hdr
->ProcessId
= cpu_to_le32((__u16
)current
->tgid
);
107 hdr
->TreeId
= tcon
->tid
;
108 /* Uid is not converted */
110 hdr
->SessionId
= tcon
->ses
->Suid
;
111 /* BB check following DFS flags BB */
112 /* BB do we have to add check for SHI1005_FLAGS_DFS_ROOT too? */
113 /* if (tcon->share_flags & SHI1005_FLAGS_DFS)
114 hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
115 /* BB how does SMB2 do case sensitive? */
117 hdr->Flags |= SMBFLG_CASELESS; */
118 /* if (tcon->ses && tcon->ses->server &&
119 (tcon->ses->server->sec_mode & SECMODE_SIGN_REQUIRED))
120 hdr->Flags |= SMB2_FLAGS_SIGNED; */
122 pdu
->StructureSize2
= cpu_to_le16(parmsize
);
127 smb2_reconnect(__le16 smb2_command
, struct cifs_tcon
*tcon
)
130 /* BB add missing code here */
135 * Allocate and return pointer to an SMB request hdr, and set basic
136 * SMB information in the SMB header. If the return code is zero, this
137 * function must have filled in request_buf pointer.
140 small_smb2_init(__le16 smb2_command
, struct cifs_tcon
*tcon
,
145 rc
= smb2_reconnect(smb2_command
, tcon
);
149 /* BB eventually switch this to SMB2 specific small buf size */
150 *request_buf
= cifs_small_buf_get();
151 if (*request_buf
== NULL
) {
152 /* BB should we add a retry in here if not a writepage? */
156 smb2_hdr_assemble((struct smb2_hdr
*) *request_buf
, smb2_command
, tcon
);
159 #ifdef CONFIG_CIFS_STATS2
161 uint16_t com_code = le16_to_cpu(smb2_command);
162 cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
165 cifs_stats_inc(&tcon
->num_smbs_sent
);
172 free_rsp_buf(int resp_buftype
, void *rsp
)
174 if (resp_buftype
== CIFS_SMALL_BUFFER
)
175 cifs_small_buf_release(rsp
);
176 else if (resp_buftype
== CIFS_LARGE_BUFFER
)
177 cifs_buf_release(rsp
);
180 #define SMB2_NUM_PROT 1
184 #define BAD_PROT 0xFFFF
186 #define SMB2_PROT_ID 0x0202
187 #define SMB21_PROT_ID 0x0210
188 #define BAD_PROT_ID 0xFFFF
193 } smb2protocols
[] = {
194 {SMB2_PROT
, cpu_to_le16(SMB2_PROT_ID
)},
195 {SMB21_PROT
, cpu_to_le16(SMB21_PROT_ID
)},
196 {BAD_PROT
, cpu_to_le16(BAD_PROT_ID
)}
201 * SMB2 Worker functions follow:
203 * The general structure of the worker functions is:
204 * 1) Call smb2_init (assembles SMB2 header)
205 * 2) Initialize SMB2 command specific fields in fixed length area of SMB
206 * 3) Call smb_sendrcv2 (sends request on socket and waits for response)
207 * 4) Decode SMB2 command specific fields in the fixed length area
208 * 5) Decode variable length data area (if any for this SMB2 command type)
209 * 6) Call free smb buffer
215 SMB2_negotiate(const unsigned int xid
, struct cifs_ses
*ses
)
217 struct smb2_negotiate_req
*req
;
218 struct smb2_negotiate_rsp
*rsp
;
222 struct TCP_Server_Info
*server
;
223 unsigned int sec_flags
;
226 int blob_offset
, blob_length
;
228 int flags
= CIFS_NEG_OP
;
230 cFYI(1, "Negotiate protocol");
233 server
= ses
->server
;
239 rc
= small_smb2_init(SMB2_NEGOTIATE
, NULL
, (void **) &req
);
243 /* if any of auth flags (ie not sign or seal) are overriden use them */
244 if (ses
->overrideSecFlg
& (~(CIFSSEC_MUST_SIGN
| CIFSSEC_MUST_SEAL
)))
245 sec_flags
= ses
->overrideSecFlg
; /* BB FIXME fix sign flags?*/
246 else /* if override flags set only sign/seal OR them with global auth */
247 sec_flags
= global_secflags
| ses
->overrideSecFlg
;
249 cFYI(1, "sec_flags 0x%x", sec_flags
);
251 req
->hdr
.SessionId
= 0;
253 for (i
= 0; i
< SMB2_NUM_PROT
; i
++)
254 req
->Dialects
[i
] = smb2protocols
[i
].name
;
256 req
->DialectCount
= cpu_to_le16(i
);
257 inc_rfc1001_len(req
, i
* 2);
259 /* only one of SMB2 signing flags may be set in SMB2 request */
260 if ((sec_flags
& CIFSSEC_MUST_SIGN
) == CIFSSEC_MUST_SIGN
)
261 temp
= SMB2_NEGOTIATE_SIGNING_REQUIRED
;
262 else if (sec_flags
& CIFSSEC_MAY_SIGN
) /* MAY_SIGN is a single flag */
263 temp
= SMB2_NEGOTIATE_SIGNING_ENABLED
;
265 req
->SecurityMode
= cpu_to_le16(temp
);
267 req
->Capabilities
= cpu_to_le32(SMB2_GLOBAL_CAP_DFS
);
269 iov
[0].iov_base
= (char *)req
;
270 /* 4 for rfc1002 length field */
271 iov
[0].iov_len
= get_rfc1002_length(req
) + 4;
273 rc
= SendReceive2(xid
, ses
, iov
, 1, &resp_buftype
, flags
);
275 rsp
= (struct smb2_negotiate_rsp
*)iov
[0].iov_base
;
277 * No tcon so can't do
278 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
288 cFYI(1, "mode 0x%x", rsp
->SecurityMode
);
290 if (rsp
->DialectRevision
== smb2protocols
[SMB21_PROT
].name
)
291 cFYI(1, "negotiated smb2.1 dialect");
292 else if (rsp
->DialectRevision
== smb2protocols
[SMB2_PROT
].name
)
293 cFYI(1, "negotiated smb2 dialect");
295 cERROR(1, "Illegal dialect returned by server %d",
296 le16_to_cpu(rsp
->DialectRevision
));
300 server
->dialect
= le16_to_cpu(rsp
->DialectRevision
);
302 server
->maxBuf
= le32_to_cpu(rsp
->MaxTransactSize
);
303 server
->max_read
= le32_to_cpu(rsp
->MaxReadSize
);
304 server
->max_write
= le32_to_cpu(rsp
->MaxWriteSize
);
305 /* BB Do we need to validate the SecurityMode? */
306 server
->sec_mode
= le16_to_cpu(rsp
->SecurityMode
);
307 server
->capabilities
= le32_to_cpu(rsp
->Capabilities
);
309 security_blob
= smb2_get_data_area_len(&blob_offset
, &blob_length
,
311 if (blob_length
== 0) {
312 cERROR(1, "missing security blob on negprot");
316 #ifdef CONFIG_SMB2_ASN1 /* BB REMOVEME when updated asn1.c ready */
317 rc
= decode_neg_token_init(security_blob
, blob_length
,
328 free_rsp_buf(resp_buftype
, rsp
);