2 Unix SMB2 implementation.
4 Copyright (C) Stefan Metzmacher 2006
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/smb2/smb2.h"
22 #include "libcli/smb2/smb2_calls.h"
23 #include "smb_server/smb_server.h"
24 #include "smb_server/service_smb_proto.h"
25 #include "smb_server/smb2/smb2_server.h"
26 #include "ntvfs/ntvfs.h"
27 #include "librpc/gen_ndr/ndr_security.h"
29 struct smb2srv_getinfo_op
{
30 struct smb2srv_request
*req
;
31 struct smb2_getinfo
*info
;
33 NTSTATUS (*send_fn
)(struct smb2srv_getinfo_op
*op
);
36 static void smb2srv_getinfo_send(struct ntvfs_request
*ntvfs
)
38 struct smb2srv_getinfo_op
*op
;
39 struct smb2srv_request
*req
;
42 * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
43 * so we need to translated it here
45 if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL
, ntvfs
->async_states
->status
)) {
46 ntvfs
->async_states
->status
= NT_STATUS_INVALID_INFO_CLASS
;
49 SMB2SRV_CHECK_ASYNC_STATUS(op
, struct smb2srv_getinfo_op
);
51 ZERO_STRUCT(op
->info
->out
);
53 SMB2SRV_CHECK(op
->send_fn(op
));
56 SMB2SRV_CHECK(smb2srv_setup_reply(req
, 0x08, true, op
->info
->out
.blob
.length
));
58 /* TODO: this is maybe a o16s32_blob */
59 SMB2SRV_CHECK(smb2_push_o16s16_blob(&req
->out
, 0x02, op
->info
->out
.blob
));
60 SSVAL(req
->out
.body
, 0x06, 0);
62 smb2srv_send_reply(req
);
65 static NTSTATUS
smb2srv_getinfo_file_send(struct smb2srv_getinfo_op
*op
)
67 union smb_fileinfo
*io
= talloc_get_type(op
->io_ptr
, union smb_fileinfo
);
70 status
= smbsrv_push_passthru_fileinfo(op
->req
,
72 io
->generic
.level
, io
,
74 NT_STATUS_NOT_OK_RETURN(status
);
79 static NTSTATUS
smb2srv_getinfo_file(struct smb2srv_getinfo_op
*op
, uint8_t smb2_level
)
81 union smb_fileinfo
*io
;
83 io
= talloc(op
, union smb_fileinfo
);
84 NT_STATUS_HAVE_NO_MEMORY(io
);
86 switch (op
->info
->in
.level
) {
87 case RAW_FILEINFO_SMB2_ALL_EAS
:
88 io
->all_eas
.level
= op
->info
->in
.level
;
89 io
->all_eas
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
90 io
->all_eas
.in
.continue_flags
= op
->info
->in
.flags2
;
93 case RAW_FILEINFO_SMB2_ALL_INFORMATION
:
94 io
->all_info2
.level
= op
->info
->in
.level
;
95 io
->all_info2
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
99 /* the rest directly maps to the passthru levels */
100 io
->generic
.level
= smb2_level
+ 1000;
101 io
->generic
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
106 op
->send_fn
= smb2srv_getinfo_file_send
;
108 return ntvfs_qfileinfo(op
->req
->ntvfs
, io
);
111 static NTSTATUS
smb2srv_getinfo_fs_send(struct smb2srv_getinfo_op
*op
)
113 union smb_fsinfo
*io
= talloc_get_type(op
->io_ptr
, union smb_fsinfo
);
116 status
= smbsrv_push_passthru_fsinfo(op
->req
,
118 io
->generic
.level
, io
,
120 NT_STATUS_NOT_OK_RETURN(status
);
125 static NTSTATUS
smb2srv_getinfo_fs(struct smb2srv_getinfo_op
*op
, uint8_t smb2_level
)
127 union smb_fsinfo
*io
;
129 io
= talloc(op
, union smb_fsinfo
);
130 NT_STATUS_HAVE_NO_MEMORY(io
);
132 /* the rest directly maps to the passthru levels */
133 io
->generic
.level
= smb2_level
+ 1000;
135 /* TODO: allow qfsinfo only the share root directory handle */
138 op
->send_fn
= smb2srv_getinfo_fs_send
;
140 return ntvfs_fsinfo(op
->req
->ntvfs
, io
);
143 static NTSTATUS
smb2srv_getinfo_security_send(struct smb2srv_getinfo_op
*op
)
145 union smb_fileinfo
*io
= talloc_get_type(op
->io_ptr
, union smb_fileinfo
);
148 status
= ndr_push_struct_blob(&op
->info
->out
.blob
, op
->req
,
149 io
->query_secdesc
.out
.sd
,
150 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
151 NT_STATUS_NOT_OK_RETURN(status
);
156 static NTSTATUS
smb2srv_getinfo_security(struct smb2srv_getinfo_op
*op
, uint8_t smb2_level
)
158 union smb_fileinfo
*io
;
160 switch (smb2_level
) {
162 io
= talloc(op
, union smb_fileinfo
);
163 NT_STATUS_HAVE_NO_MEMORY(io
);
165 io
->query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
166 io
->query_secdesc
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
167 io
->query_secdesc
.in
.secinfo_flags
= op
->info
->in
.flags
;
170 op
->send_fn
= smb2srv_getinfo_security_send
;
172 return ntvfs_qfileinfo(op
->req
->ntvfs
, io
);
175 return NT_STATUS_INVALID_PARAMETER
;
178 static NTSTATUS
smb2srv_getinfo_backend(struct smb2srv_getinfo_op
*op
)
183 smb2_class
= 0xFF & op
->info
->in
.level
;
184 smb2_level
= 0xFF & (op
->info
->in
.level
>>8);
186 switch (smb2_class
) {
187 case SMB2_GETINFO_FILE
:
188 return smb2srv_getinfo_file(op
, smb2_level
);
190 case SMB2_GETINFO_FS
:
191 return smb2srv_getinfo_fs(op
, smb2_level
);
193 case SMB2_GETINFO_SECURITY
:
194 return smb2srv_getinfo_security(op
, smb2_level
);
197 return NT_STATUS_NOT_SUPPORTED
;
200 return NT_STATUS_INVALID_PARAMETER
;
203 void smb2srv_getinfo_recv(struct smb2srv_request
*req
)
205 struct smb2_getinfo
*info
;
206 struct smb2srv_getinfo_op
*op
;
208 SMB2SRV_CHECK_BODY_SIZE(req
, 0x28, true);
209 SMB2SRV_TALLOC_IO_PTR(info
, struct smb2_getinfo
);
210 /* this overwrites req->io_ptr !*/
211 SMB2SRV_TALLOC_IO_PTR(op
, struct smb2srv_getinfo_op
);
216 SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
218 info
->in
.level
= SVAL(req
->in
.body
, 0x02);
219 info
->in
.max_response_size
= IVAL(req
->in
.body
, 0x04);
220 info
->in
.unknown1
= IVAL(req
->in
.body
, 0x08);
221 info
->in
.unknown2
= IVAL(req
->in
.body
, 0x0C);
222 info
->in
.flags
= IVAL(req
->in
.body
, 0x10);
223 info
->in
.flags2
= IVAL(req
->in
.body
, 0x14);
224 info
->in
.file
.ntvfs
= smb2srv_pull_handle(req
, req
->in
.body
, 0x18);
226 SMB2SRV_CHECK_FILE_HANDLE(info
->in
.file
.ntvfs
);
227 SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op
));
230 struct smb2srv_setinfo_op
{
231 struct smb2srv_request
*req
;
232 struct smb2_setinfo
*info
;
235 static void smb2srv_setinfo_send(struct ntvfs_request
*ntvfs
)
237 struct smb2srv_setinfo_op
*op
;
238 struct smb2srv_request
*req
;
241 * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
242 * so we need to translated it here
244 if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL
, ntvfs
->async_states
->status
)) {
245 ntvfs
->async_states
->status
= NT_STATUS_INVALID_INFO_CLASS
;
248 SMB2SRV_CHECK_ASYNC_STATUS(op
, struct smb2srv_setinfo_op
);
250 SMB2SRV_CHECK(smb2srv_setup_reply(req
, 0x02, false, 0));
252 smb2srv_send_reply(req
);
255 static NTSTATUS
smb2srv_setinfo_file(struct smb2srv_setinfo_op
*op
, uint8_t smb2_level
)
257 union smb_setfileinfo
*io
;
260 io
= talloc(op
, union smb_setfileinfo
);
261 NT_STATUS_HAVE_NO_MEMORY(io
);
263 /* the levels directly map to the passthru levels */
264 io
->generic
.level
= smb2_level
+ 1000;
265 io
->generic
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
267 status
= smbsrv_pull_passthru_sfileinfo(io
, io
->generic
.level
, io
,
270 NT_STATUS_NOT_OK_RETURN(status
);
272 return ntvfs_setfileinfo(op
->req
->ntvfs
, io
);
275 static NTSTATUS
smb2srv_setinfo_fs(struct smb2srv_setinfo_op
*op
, uint8_t smb2_level
)
277 switch (smb2_level
) {
279 return NT_STATUS_NOT_IMPLEMENTED
;
282 return NT_STATUS_ACCESS_DENIED
;
285 return NT_STATUS_ACCESS_DENIED
;
288 return NT_STATUS_ACCESS_DENIED
;
291 return NT_STATUS_INVALID_INFO_CLASS
;
294 static NTSTATUS
smb2srv_setinfo_security(struct smb2srv_setinfo_op
*op
, uint8_t smb2_level
)
296 union smb_setfileinfo
*io
;
299 switch (smb2_level
) {
301 io
= talloc(op
, union smb_setfileinfo
);
302 NT_STATUS_HAVE_NO_MEMORY(io
);
304 io
->set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
305 io
->set_secdesc
.in
.file
.ntvfs
= op
->info
->in
.file
.ntvfs
;
306 io
->set_secdesc
.in
.secinfo_flags
= op
->info
->in
.flags
;
308 io
->set_secdesc
.in
.sd
= talloc(io
, struct security_descriptor
);
309 NT_STATUS_HAVE_NO_MEMORY(io
->set_secdesc
.in
.sd
);
311 status
= ndr_pull_struct_blob(&op
->info
->in
.blob
, io
,
312 io
->set_secdesc
.in
.sd
,
313 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
314 NT_STATUS_NOT_OK_RETURN(status
);
316 return ntvfs_setfileinfo(op
->req
->ntvfs
, io
);
319 return NT_STATUS_INVALID_INFO_CLASS
;
322 static NTSTATUS
smb2srv_setinfo_backend(struct smb2srv_setinfo_op
*op
)
327 smb2_class
= 0xFF & op
->info
->in
.level
;
328 smb2_level
= 0xFF & (op
->info
->in
.level
>>8);
330 switch (smb2_class
) {
331 case SMB2_GETINFO_FILE
:
332 return smb2srv_setinfo_file(op
, smb2_level
);
334 case SMB2_GETINFO_FS
:
335 return smb2srv_setinfo_fs(op
, smb2_level
);
337 case SMB2_GETINFO_SECURITY
:
338 return smb2srv_setinfo_security(op
, smb2_level
);
341 return NT_STATUS_NOT_SUPPORTED
;
344 return NT_STATUS_INVALID_PARAMETER
;
347 void smb2srv_setinfo_recv(struct smb2srv_request
*req
)
349 struct smb2_setinfo
*info
;
350 struct smb2srv_setinfo_op
*op
;
352 SMB2SRV_CHECK_BODY_SIZE(req
, 0x20, true);
353 SMB2SRV_TALLOC_IO_PTR(info
, struct smb2_setinfo
);
354 /* this overwrites req->io_ptr !*/
355 SMB2SRV_TALLOC_IO_PTR(op
, struct smb2srv_setinfo_op
);
358 SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
360 info
->in
.level
= SVAL(req
->in
.body
, 0x02);
361 SMB2SRV_CHECK(smb2_pull_s32o32_blob(&req
->in
, info
, req
->in
.body
+0x04, &info
->in
.blob
));
362 info
->in
.flags
= IVAL(req
->in
.body
, 0x0C);
363 info
->in
.file
.ntvfs
= smb2srv_pull_handle(req
, req
->in
.body
, 0x10);
365 SMB2SRV_CHECK_FILE_HANDLE(info
->in
.file
.ntvfs
);
366 SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_setinfo_backend(op
));