2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-2003
5 Copyright (C) James J Myers 2003 <myersjj@samba.org>
6 Copyright (C) Stefan Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific SMB commands
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
30 #include "libcli/nbt/libnbt.h"
33 /****************************************************************************
34 Reply to a simple request (async send)
35 ****************************************************************************/
36 static void reply_simple_send(struct ntvfs_request
*ntvfs
)
38 struct smbsrv_request
*req
;
40 SMBSRV_CHECK_ASYNC_STATUS_SIMPLE
;
42 smbsrv_setup_reply(req
, 0, 0);
43 smbsrv_send_reply(req
);
47 /****************************************************************************
48 Reply to a tcon (async reply)
49 ****************************************************************************/
50 static void reply_tcon_send(struct ntvfs_request
*ntvfs
)
52 struct smbsrv_request
*req
;
55 SMBSRV_CHECK_ASYNC_STATUS(con
, union smb_tcon
);
58 smbsrv_setup_reply(req
, 2, 0);
60 SSVAL(req
->out
.vwv
, VWV(0), con
->tcon
.out
.max_xmit
);
61 SSVAL(req
->out
.vwv
, VWV(1), con
->tcon
.out
.tid
);
62 SSVAL(req
->out
.hdr
, HDR_TID
, req
->tcon
->tid
);
64 smbsrv_send_reply(req
);
67 /****************************************************************************
69 ****************************************************************************/
70 void smbsrv_reply_tcon(struct smbsrv_request
*req
)
77 SMBSRV_CHECK_WCT(req
, 0);
79 SMBSRV_TALLOC_IO_PTR(con
, union smb_tcon
);
81 con
->tcon
.level
= RAW_TCON_TCON
;
84 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.service
, p
, STR_TERMINATE
);
85 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.password
, p
, STR_TERMINATE
);
86 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.dev
, p
, STR_TERMINATE
);
88 if (!con
->tcon
.in
.service
|| !con
->tcon
.in
.password
|| !con
->tcon
.in
.dev
) {
89 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
93 /* Instantiate backend */
94 status
= smbsrv_tcon_backend(req
, con
);
95 if (!NT_STATUS_IS_OK(status
)) {
96 smbsrv_send_error(req
, status
);
100 SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
102 /* Invoke NTVFS connection hook */
103 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req
->ntvfs
, con
));
107 /****************************************************************************
108 Reply to a tcon and X (async reply)
109 ****************************************************************************/
110 static void reply_tcon_and_X_send(struct ntvfs_request
*ntvfs
)
112 struct smbsrv_request
*req
;
115 SMBSRV_CHECK_ASYNC_STATUS(con
, union smb_tcon
);
117 /* construct reply - two variants */
118 if (req
->smb_conn
->negotiate
.protocol
< PROTOCOL_NT1
) {
119 smbsrv_setup_reply(req
, 2, 0);
121 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
122 SSVAL(req
->out
.vwv
, VWV(1), 0);
124 req_push_str(req
, NULL
, con
->tconx
.out
.dev_type
, -1, STR_TERMINATE
|STR_ASCII
);
126 smbsrv_setup_reply(req
, 3, 0);
128 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
129 SSVAL(req
->out
.vwv
, VWV(1), 0);
130 SSVAL(req
->out
.vwv
, VWV(2), con
->tconx
.out
.options
);
132 req_push_str(req
, NULL
, con
->tconx
.out
.dev_type
, -1, STR_TERMINATE
|STR_ASCII
);
133 req_push_str(req
, NULL
, con
->tconx
.out
.fs_type
, -1, STR_TERMINATE
);
136 /* set the incoming and outgoing tid to the just created one */
137 SSVAL(req
->in
.hdr
, HDR_TID
, con
->tconx
.out
.tid
);
138 SSVAL(req
->out
.hdr
,HDR_TID
, con
->tconx
.out
.tid
);
140 smbsrv_chain_reply(req
);
143 /****************************************************************************
144 Reply to a tcon and X.
145 ****************************************************************************/
146 void smbsrv_reply_tcon_and_X(struct smbsrv_request
*req
)
153 SMBSRV_TALLOC_IO_PTR(con
, union smb_tcon
);
155 con
->tconx
.level
= RAW_TCON_TCONX
;
158 SMBSRV_CHECK_WCT(req
, 4);
160 con
->tconx
.in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
161 passlen
= SVAL(req
->in
.vwv
, VWV(3));
165 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen
, &con
->tconx
.in
.password
)) {
166 smbsrv_send_error(req
, NT_STATUS_ILL_FORMED_PASSWORD
);
171 p
+= req_pull_string(&req
->in
.bufinfo
, &con
->tconx
.in
.path
, p
, -1, STR_TERMINATE
);
172 p
+= req_pull_string(&req
->in
.bufinfo
, &con
->tconx
.in
.device
, p
, -1, STR_ASCII
);
174 if (!con
->tconx
.in
.path
|| !con
->tconx
.in
.device
) {
175 smbsrv_send_error(req
, NT_STATUS_BAD_DEVICE_TYPE
);
179 /* Instantiate backend */
180 status
= smbsrv_tcon_backend(req
, con
);
181 if (!NT_STATUS_IS_OK(status
)) {
182 smbsrv_send_error(req
, status
);
186 SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
188 /* Invoke NTVFS connection hook */
189 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req
->ntvfs
, con
));
193 /****************************************************************************
194 Reply to an unknown request
195 ****************************************************************************/
196 void smbsrv_reply_unknown(struct smbsrv_request
*req
)
200 type
= CVAL(req
->in
.hdr
, HDR_COM
);
202 DEBUG(0,("unknown command type %d (0x%X)\n", type
, type
));
204 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRunknownsmb
));
208 /****************************************************************************
209 Reply to an ioctl (async reply)
210 ****************************************************************************/
211 static void reply_ioctl_send(struct ntvfs_request
*ntvfs
)
213 struct smbsrv_request
*req
;
216 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_ioctl
);
218 /* the +1 is for nicer alignment */
219 smbsrv_setup_reply(req
, 8, io
->ioctl
.out
.blob
.length
+1);
220 SSVAL(req
->out
.vwv
, VWV(1), io
->ioctl
.out
.blob
.length
);
221 SSVAL(req
->out
.vwv
, VWV(5), io
->ioctl
.out
.blob
.length
);
222 SSVAL(req
->out
.vwv
, VWV(6), PTR_DIFF(req
->out
.data
, req
->out
.hdr
) + 1);
224 memcpy(req
->out
.data
+1, io
->ioctl
.out
.blob
.data
, io
->ioctl
.out
.blob
.length
);
226 smbsrv_send_reply(req
);
229 /****************************************************************************
231 ****************************************************************************/
232 void smbsrv_reply_ioctl(struct smbsrv_request
*req
)
237 SMBSRV_CHECK_WCT(req
, 3);
238 SMBSRV_TALLOC_IO_PTR(io
, union smb_ioctl
);
239 SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
241 io
->ioctl
.level
= RAW_IOCTL_IOCTL
;
242 io
->ioctl
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
243 io
->ioctl
.in
.request
= IVAL(req
->in
.vwv
, VWV(1));
245 SMBSRV_CHECK_FILE_HANDLE_ERROR(io
->ioctl
.in
.file
.ntvfs
,
246 NT_STATUS_DOS(ERRSRV
, ERRerror
));
247 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req
->ntvfs
, io
));
251 /****************************************************************************
253 ****************************************************************************/
254 void smbsrv_reply_chkpth(struct smbsrv_request
*req
)
256 union smb_chkpath
*io
;
258 SMBSRV_TALLOC_IO_PTR(io
, union smb_chkpath
);
259 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
261 req_pull_ascii4(&req
->in
.bufinfo
, &io
->chkpath
.in
.path
, req
->in
.data
, STR_TERMINATE
);
263 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req
->ntvfs
, io
));
266 /****************************************************************************
267 Reply to a getatr (async reply)
268 ****************************************************************************/
269 static void reply_getatr_send(struct ntvfs_request
*ntvfs
)
271 struct smbsrv_request
*req
;
272 union smb_fileinfo
*st
;
274 SMBSRV_CHECK_ASYNC_STATUS(st
, union smb_fileinfo
);
276 /* construct reply */
277 smbsrv_setup_reply(req
, 10, 0);
279 SSVAL(req
->out
.vwv
, VWV(0), st
->getattr
.out
.attrib
);
280 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(1), st
->getattr
.out
.write_time
);
281 SIVAL(req
->out
.vwv
, VWV(3), st
->getattr
.out
.size
);
283 SMBSRV_VWV_RESERVED(5, 5);
285 smbsrv_send_reply(req
);
289 /****************************************************************************
291 ****************************************************************************/
292 void smbsrv_reply_getatr(struct smbsrv_request
*req
)
294 union smb_fileinfo
*st
;
296 SMBSRV_TALLOC_IO_PTR(st
, union smb_fileinfo
);
297 SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
299 st
->getattr
.level
= RAW_FILEINFO_GETATTR
;
302 req_pull_ascii4(&req
->in
.bufinfo
, &st
->getattr
.in
.file
.path
, req
->in
.data
, STR_TERMINATE
);
303 if (!st
->getattr
.in
.file
.path
) {
304 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
308 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req
->ntvfs
, st
));
312 /****************************************************************************
314 ****************************************************************************/
315 void smbsrv_reply_setatr(struct smbsrv_request
*req
)
317 union smb_setfileinfo
*st
;
320 SMBSRV_CHECK_WCT(req
, 8);
321 SMBSRV_TALLOC_IO_PTR(st
, union smb_setfileinfo
);
322 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
324 st
->setattr
.level
= RAW_SFILEINFO_SETATTR
;
325 st
->setattr
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
326 st
->setattr
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
328 req_pull_ascii4(&req
->in
.bufinfo
, &st
->setattr
.in
.file
.path
, req
->in
.data
, STR_TERMINATE
);
330 if (!st
->setattr
.in
.file
.path
) {
331 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
335 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req
->ntvfs
, st
));
339 /****************************************************************************
340 Reply to a dskattr (async reply)
341 ****************************************************************************/
342 static void reply_dskattr_send(struct ntvfs_request
*ntvfs
)
344 struct smbsrv_request
*req
;
345 union smb_fsinfo
*fs
;
347 SMBSRV_CHECK_ASYNC_STATUS(fs
, union smb_fsinfo
);
349 /* construct reply */
350 smbsrv_setup_reply(req
, 5, 0);
352 SSVAL(req
->out
.vwv
, VWV(0), fs
->dskattr
.out
.units_total
);
353 SSVAL(req
->out
.vwv
, VWV(1), fs
->dskattr
.out
.blocks_per_unit
);
354 SSVAL(req
->out
.vwv
, VWV(2), fs
->dskattr
.out
.block_size
);
355 SSVAL(req
->out
.vwv
, VWV(3), fs
->dskattr
.out
.units_free
);
357 SMBSRV_VWV_RESERVED(4, 1);
359 smbsrv_send_reply(req
);
363 /****************************************************************************
365 ****************************************************************************/
366 void smbsrv_reply_dskattr(struct smbsrv_request
*req
)
368 union smb_fsinfo
*fs
;
370 SMBSRV_TALLOC_IO_PTR(fs
, union smb_fsinfo
);
371 SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
373 fs
->dskattr
.level
= RAW_QFS_DSKATTR
;
375 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req
->ntvfs
, fs
));
379 /****************************************************************************
380 Reply to an open (async reply)
381 ****************************************************************************/
382 static void reply_open_send(struct ntvfs_request
*ntvfs
)
384 struct smbsrv_request
*req
;
387 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
389 /* construct reply */
390 smbsrv_setup_reply(req
, 7, 0);
392 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->openold
.out
.file
.ntvfs
);
393 SSVAL(req
->out
.vwv
, VWV(1), oi
->openold
.out
.attrib
);
394 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(2), oi
->openold
.out
.write_time
);
395 SIVAL(req
->out
.vwv
, VWV(4), oi
->openold
.out
.size
);
396 SSVAL(req
->out
.vwv
, VWV(6), oi
->openold
.out
.rmode
);
398 smbsrv_send_reply(req
);
401 /****************************************************************************
403 ****************************************************************************/
404 void smbsrv_reply_open(struct smbsrv_request
*req
)
409 SMBSRV_CHECK_WCT(req
, 2);
410 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
411 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
413 oi
->openold
.level
= RAW_OPEN_OPEN
;
414 oi
->openold
.in
.open_mode
= SVAL(req
->in
.vwv
, VWV(0));
415 oi
->openold
.in
.search_attrs
= SVAL(req
->in
.vwv
, VWV(1));
417 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->openold
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
419 if (!oi
->openold
.in
.fname
) {
420 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
424 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
428 /****************************************************************************
429 Reply to an open and X (async reply)
430 ****************************************************************************/
431 static void reply_open_and_X_send(struct ntvfs_request
*ntvfs
)
433 struct smbsrv_request
*req
;
436 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
438 /* build the reply */
439 if (oi
->openx
.in
.flags
& OPENX_FLAGS_EXTENDED_RETURN
) {
440 smbsrv_setup_reply(req
, 19, 0);
442 smbsrv_setup_reply(req
, 15, 0);
445 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
446 SSVAL(req
->out
.vwv
, VWV(1), 0);
447 smbsrv_push_fnum(req
->out
.vwv
, VWV(2), oi
->openx
.out
.file
.ntvfs
);
448 SSVAL(req
->out
.vwv
, VWV(3), oi
->openx
.out
.attrib
);
449 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(4), oi
->openx
.out
.write_time
);
450 SIVAL(req
->out
.vwv
, VWV(6), oi
->openx
.out
.size
);
451 SSVAL(req
->out
.vwv
, VWV(8), oi
->openx
.out
.access
);
452 SSVAL(req
->out
.vwv
, VWV(9), oi
->openx
.out
.ftype
);
453 SSVAL(req
->out
.vwv
, VWV(10),oi
->openx
.out
.devstate
);
454 SSVAL(req
->out
.vwv
, VWV(11),oi
->openx
.out
.action
);
455 SIVAL(req
->out
.vwv
, VWV(12),oi
->openx
.out
.unique_fid
);
456 SSVAL(req
->out
.vwv
, VWV(14),0); /* reserved */
457 if (oi
->openx
.in
.flags
& OPENX_FLAGS_EXTENDED_RETURN
) {
458 SIVAL(req
->out
.vwv
, VWV(15),oi
->openx
.out
.access_mask
);
459 SMBSRV_VWV_RESERVED(17, 2);
462 req
->chained_fnum
= SVAL(req
->out
.vwv
, VWV(2));
464 smbsrv_chain_reply(req
);
468 /****************************************************************************
469 Reply to an open and X.
470 ****************************************************************************/
471 void smbsrv_reply_open_and_X(struct smbsrv_request
*req
)
475 /* parse the request */
476 SMBSRV_CHECK_WCT(req
, 15);
477 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
478 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
480 oi
->openx
.level
= RAW_OPEN_OPENX
;
481 oi
->openx
.in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
482 oi
->openx
.in
.open_mode
= SVAL(req
->in
.vwv
, VWV(3));
483 oi
->openx
.in
.search_attrs
= SVAL(req
->in
.vwv
, VWV(4));
484 oi
->openx
.in
.file_attrs
= SVAL(req
->in
.vwv
, VWV(5));
485 oi
->openx
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(6));
486 oi
->openx
.in
.open_func
= SVAL(req
->in
.vwv
, VWV(8));
487 oi
->openx
.in
.size
= IVAL(req
->in
.vwv
, VWV(9));
488 oi
->openx
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(11));
490 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->openx
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
492 if (!oi
->openx
.in
.fname
) {
493 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
497 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
501 /****************************************************************************
502 Reply to a mknew or a create.
503 ****************************************************************************/
504 static void reply_mknew_send(struct ntvfs_request
*ntvfs
)
506 struct smbsrv_request
*req
;
509 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
511 /* build the reply */
512 smbsrv_setup_reply(req
, 1, 0);
514 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->mknew
.out
.file
.ntvfs
);
516 smbsrv_send_reply(req
);
520 /****************************************************************************
521 Reply to a mknew or a create.
522 ****************************************************************************/
523 void smbsrv_reply_mknew(struct smbsrv_request
*req
)
527 /* parse the request */
528 SMBSRV_CHECK_WCT(req
, 3);
529 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
530 SMBSRV_SETUP_NTVFS_REQUEST(reply_mknew_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
532 if (CVAL(req
->in
.hdr
, HDR_COM
) == SMBmknew
) {
533 oi
->mknew
.level
= RAW_OPEN_MKNEW
;
535 oi
->mknew
.level
= RAW_OPEN_CREATE
;
537 oi
->mknew
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
538 oi
->mknew
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
540 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->mknew
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
542 if (!oi
->mknew
.in
.fname
) {
543 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
547 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
550 /****************************************************************************
551 Reply to a create temporary file (async reply)
552 ****************************************************************************/
553 static void reply_ctemp_send(struct ntvfs_request
*ntvfs
)
555 struct smbsrv_request
*req
;
558 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
560 /* build the reply */
561 smbsrv_setup_reply(req
, 1, 0);
563 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->ctemp
.out
.file
.ntvfs
);
565 /* the returned filename is relative to the directory */
566 req_push_str(req
, NULL
, oi
->ctemp
.out
.name
, -1, STR_TERMINATE
| STR_ASCII
);
568 smbsrv_send_reply(req
);
571 /****************************************************************************
572 Reply to a create temporary file.
573 ****************************************************************************/
574 void smbsrv_reply_ctemp(struct smbsrv_request
*req
)
578 /* parse the request */
579 SMBSRV_CHECK_WCT(req
, 3);
580 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
581 SMBSRV_SETUP_NTVFS_REQUEST(reply_ctemp_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
583 oi
->ctemp
.level
= RAW_OPEN_CTEMP
;
584 oi
->ctemp
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
585 oi
->ctemp
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
587 /* the filename is actually a directory name, the server provides a filename
589 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->ctemp
.in
.directory
, req
->in
.data
, STR_TERMINATE
);
591 if (!oi
->ctemp
.in
.directory
) {
592 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
596 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
600 /****************************************************************************
602 ****************************************************************************/
603 void smbsrv_reply_unlink(struct smbsrv_request
*req
)
605 union smb_unlink
*unl
;
607 /* parse the request */
608 SMBSRV_CHECK_WCT(req
, 1);
609 SMBSRV_TALLOC_IO_PTR(unl
, union smb_unlink
);
610 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
612 unl
->unlink
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
614 req_pull_ascii4(&req
->in
.bufinfo
, &unl
->unlink
.in
.pattern
, req
->in
.data
, STR_TERMINATE
);
616 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_unlink(req
->ntvfs
, unl
));
620 /****************************************************************************
621 Reply to a readbraw (core+ protocol).
622 this is a strange packet because it doesn't use a standard SMB header in the reply,
623 only the 4 byte NBT header
624 This command must be replied to synchronously
625 ****************************************************************************/
626 void smbsrv_reply_readbraw(struct smbsrv_request
*req
)
631 io
.readbraw
.level
= RAW_READ_READBRAW
;
633 /* there are two variants, one with 10 and one with 8 command words */
634 if (req
->in
.wct
< 8) {
638 io
.readbraw
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
639 io
.readbraw
.in
.offset
= IVAL(req
->in
.vwv
, VWV(1));
640 io
.readbraw
.in
.maxcnt
= SVAL(req
->in
.vwv
, VWV(3));
641 io
.readbraw
.in
.mincnt
= SVAL(req
->in
.vwv
, VWV(4));
642 io
.readbraw
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(5));
644 if (!io
.readbraw
.in
.file
.ntvfs
) {
648 /* the 64 bit variant */
649 if (req
->in
.wct
== 10) {
650 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(8));
651 io
.readbraw
.in
.offset
|= (((off_t
)offset_high
) << 32);
654 /* before calling the backend we setup the raw buffer. This
655 * saves a copy later */
656 req
->out
.size
= io
.readbraw
.in
.maxcnt
+ NBT_HDR_SIZE
;
657 req
->out
.buffer
= talloc_size(req
, req
->out
.size
);
658 if (req
->out
.buffer
== NULL
) {
661 SIVAL(req
->out
.buffer
, 0, 0); /* init NBT header */
663 /* tell the backend where to put the data */
664 io
.readbraw
.out
.data
= req
->out
.buffer
+ NBT_HDR_SIZE
;
666 /* prepare the ntvfs request */
667 req
->ntvfs
= ntvfs_request_create(req
->tcon
->ntvfs
, req
,
668 req
->session
->session_info
,
669 SVAL(req
->in
.hdr
,HDR_PID
),
676 /* call the backend */
677 status
= ntvfs_read(req
->ntvfs
, &io
);
678 if (!NT_STATUS_IS_OK(status
)) {
682 req
->out
.size
= io
.readbraw
.out
.nread
+ NBT_HDR_SIZE
;
684 smbsrv_send_reply_nosign(req
);
688 /* any failure in readbraw is equivalent to reading zero bytes */
690 req
->out
.buffer
= talloc_size(req
, req
->out
.size
);
691 SIVAL(req
->out
.buffer
, 0, 0); /* init NBT header */
693 smbsrv_send_reply_nosign(req
);
697 /****************************************************************************
698 Reply to a lockread (async reply)
699 ****************************************************************************/
700 static void reply_lockread_send(struct ntvfs_request
*ntvfs
)
702 struct smbsrv_request
*req
;
705 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_read
);
708 io
->lockread
.out
.nread
= MIN(io
->lockread
.out
.nread
,
709 req_max_data(req
) - 3);
710 req_grow_data(req
, 3 + io
->lockread
.out
.nread
);
712 /* construct reply */
713 SSVAL(req
->out
.vwv
, VWV(0), io
->lockread
.out
.nread
);
714 SMBSRV_VWV_RESERVED(1, 4);
716 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
717 SSVAL(req
->out
.data
, 1, io
->lockread
.out
.nread
);
719 smbsrv_send_reply(req
);
723 /****************************************************************************
724 Reply to a lockread (core+ protocol).
725 note that the lock is a write lock, not a read lock!
726 ****************************************************************************/
727 void smbsrv_reply_lockread(struct smbsrv_request
*req
)
732 SMBSRV_CHECK_WCT(req
, 5);
733 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
734 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
736 io
->lockread
.level
= RAW_READ_LOCKREAD
;
737 io
->lockread
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
738 io
->lockread
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
739 io
->lockread
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
740 io
->lockread
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
742 /* setup the reply packet assuming the maximum possible read */
743 smbsrv_setup_reply(req
, 5, 3 + io
->lockread
.in
.count
);
745 /* tell the backend where to put the data */
746 io
->lockread
.out
.data
= req
->out
.data
+ 3;
748 SMBSRV_CHECK_FILE_HANDLE(io
->lockread
.in
.file
.ntvfs
);
749 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
754 /****************************************************************************
755 Reply to a read (async reply)
756 ****************************************************************************/
757 static void reply_read_send(struct ntvfs_request
*ntvfs
)
759 struct smbsrv_request
*req
;
762 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_read
);
765 io
->read
.out
.nread
= MIN(io
->read
.out
.nread
,
766 req_max_data(req
) - 3);
767 req_grow_data(req
, 3 + io
->read
.out
.nread
);
769 /* construct reply */
770 SSVAL(req
->out
.vwv
, VWV(0), io
->read
.out
.nread
);
771 SMBSRV_VWV_RESERVED(1, 4);
773 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
774 SSVAL(req
->out
.data
, 1, io
->read
.out
.nread
);
776 smbsrv_send_reply(req
);
779 /****************************************************************************
781 ****************************************************************************/
782 void smbsrv_reply_read(struct smbsrv_request
*req
)
787 SMBSRV_CHECK_WCT(req
, 5);
788 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
789 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
791 io
->read
.level
= RAW_READ_READ
;
792 io
->read
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
793 io
->read
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
794 io
->read
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
795 io
->read
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
797 /* setup the reply packet assuming the maximum possible read */
798 smbsrv_setup_reply(req
, 5, 3 + io
->read
.in
.count
);
800 /* tell the backend where to put the data */
801 io
->read
.out
.data
= req
->out
.data
+ 3;
803 SMBSRV_CHECK_FILE_HANDLE(io
->read
.in
.file
.ntvfs
);
804 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
807 /****************************************************************************
808 Reply to a read and X (async reply)
809 ****************************************************************************/
810 static void reply_read_and_X_send(struct ntvfs_request
*ntvfs
)
812 struct smbsrv_request
*req
;
815 SMBSRV_CHECK_ASYNC_STATUS_ERR(io
, union smb_read
);
817 /* readx reply packets can be over-sized */
818 req
->control_flags
|= SMBSRV_REQ_CONTROL_LARGE
;
819 if (io
->readx
.in
.maxcnt
!= 0xFFFF &&
820 io
->readx
.in
.mincnt
!= 0xFFFF) {
821 req_grow_data(req
, 1 + io
->readx
.out
.nread
);
822 SCVAL(req
->out
.data
, 0, 0); /* padding */
824 req_grow_data(req
, io
->readx
.out
.nread
);
827 /* construct reply */
828 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
829 SSVAL(req
->out
.vwv
, VWV(1), 0);
830 SSVAL(req
->out
.vwv
, VWV(2), io
->readx
.out
.remaining
);
831 SSVAL(req
->out
.vwv
, VWV(3), io
->readx
.out
.compaction_mode
);
832 SMBSRV_VWV_RESERVED(4, 1);
833 SSVAL(req
->out
.vwv
, VWV(5), io
->readx
.out
.nread
);
834 SSVAL(req
->out
.vwv
, VWV(6), PTR_DIFF(io
->readx
.out
.data
, req
->out
.hdr
));
835 SSVAL(req
->out
.vwv
, VWV(7), (io
->readx
.out
.nread
>>16));
836 SMBSRV_VWV_RESERVED(8, 4);
838 if (!NT_STATUS_IS_OK(req
->ntvfs
->async_states
->status
)) {
839 smbsrv_setup_error(req
, req
->ntvfs
->async_states
->status
);
842 smbsrv_chain_reply(req
);
845 /****************************************************************************
846 Reply to a read and X.
847 ****************************************************************************/
848 void smbsrv_reply_read_and_X(struct smbsrv_request
*req
)
851 uint16_t high_part
= 0;
854 if (req
->in
.wct
!= 12) {
855 SMBSRV_CHECK_WCT(req
, 10);
858 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
859 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
861 io
->readx
.level
= RAW_READ_READX
;
862 io
->readx
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
863 io
->readx
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
864 io
->readx
.in
.maxcnt
= SVAL(req
->in
.vwv
, VWV(5));
865 io
->readx
.in
.mincnt
= SVAL(req
->in
.vwv
, VWV(6));
866 io
->readx
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(9));
867 if (req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) {
868 io
->readx
.in
.read_for_execute
= true;
870 io
->readx
.in
.read_for_execute
= false;
873 if (req
->smb_conn
->negotiate
.protocol
== PROTOCOL_NT1
) {
874 high_part
= SVAL(req
->in
.vwv
, VWV(7));
876 if (high_part
!= UINT16_MAX
) {
877 io
->readx
.in
.maxcnt
|= high_part
<< 16;
881 * Windows truncates the length to 0x10000
883 io
->readx
.in
.maxcnt
= MIN(io
->readx
.in
.maxcnt
, 0x10000);
885 /* the 64 bit variant */
886 if (req
->in
.wct
== 12) {
887 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(10));
888 io
->readx
.in
.offset
|= (((uint64_t)offset_high
) << 32);
891 /* setup the reply packet assuming the maximum possible read */
892 smbsrv_setup_reply(req
, 12, 1 + io
->readx
.in
.maxcnt
);
894 /* tell the backend where to put the data. Notice the pad byte. */
895 if (io
->readx
.in
.maxcnt
!= 0xFFFF &&
896 io
->readx
.in
.mincnt
!= 0xFFFF) {
897 io
->readx
.out
.data
= req
->out
.data
+ 1;
899 io
->readx
.out
.data
= req
->out
.data
;
902 SMBSRV_CHECK_FILE_HANDLE(io
->readx
.in
.file
.ntvfs
);
903 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
907 /****************************************************************************
908 Reply to a writebraw (core+ or LANMAN1.0 protocol).
909 ****************************************************************************/
910 void smbsrv_reply_writebraw(struct smbsrv_request
*req
)
912 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
916 /****************************************************************************
917 Reply to a writeunlock (async reply)
918 ****************************************************************************/
919 static void reply_writeunlock_send(struct ntvfs_request
*ntvfs
)
921 struct smbsrv_request
*req
;
924 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
926 /* construct reply */
927 smbsrv_setup_reply(req
, 1, 0);
929 SSVAL(req
->out
.vwv
, VWV(0), io
->writeunlock
.out
.nwritten
);
931 smbsrv_send_reply(req
);
934 /****************************************************************************
935 Reply to a writeunlock (core+).
936 ****************************************************************************/
937 void smbsrv_reply_writeunlock(struct smbsrv_request
*req
)
941 SMBSRV_CHECK_WCT(req
, 5);
942 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
943 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
945 io
->writeunlock
.level
= RAW_WRITE_WRITEUNLOCK
;
946 io
->writeunlock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
947 io
->writeunlock
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
948 io
->writeunlock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
949 io
->writeunlock
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
950 io
->writeunlock
.in
.data
= req
->in
.data
+ 3;
952 /* make sure they gave us the data they promised */
953 if (io
->writeunlock
.in
.count
+3 > req
->in
.data_size
) {
954 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
958 /* make sure the data block is big enough */
959 if (SVAL(req
->in
.data
, 1) < io
->writeunlock
.in
.count
) {
960 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
964 SMBSRV_CHECK_FILE_HANDLE(io
->writeunlock
.in
.file
.ntvfs
);
965 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
970 /****************************************************************************
971 Reply to a write (async reply)
972 ****************************************************************************/
973 static void reply_write_send(struct ntvfs_request
*ntvfs
)
975 struct smbsrv_request
*req
;
978 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
980 /* construct reply */
981 smbsrv_setup_reply(req
, 1, 0);
983 SSVAL(req
->out
.vwv
, VWV(0), io
->write
.out
.nwritten
);
985 smbsrv_send_reply(req
);
988 /****************************************************************************
990 ****************************************************************************/
991 void smbsrv_reply_write(struct smbsrv_request
*req
)
995 SMBSRV_CHECK_WCT(req
, 5);
996 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
997 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
999 io
->write
.level
= RAW_WRITE_WRITE
;
1000 io
->write
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1001 io
->write
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
1002 io
->write
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
1003 io
->write
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
1004 io
->write
.in
.data
= req
->in
.data
+ 3;
1006 /* make sure they gave us the data they promised */
1007 if (req_data_oob(&req
->in
.bufinfo
, io
->write
.in
.data
, io
->write
.in
.count
)) {
1008 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1012 /* make sure the data block is big enough */
1013 if (SVAL(req
->in
.data
, 1) < io
->write
.in
.count
) {
1014 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1018 SMBSRV_CHECK_FILE_HANDLE(io
->write
.in
.file
.ntvfs
);
1019 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1023 /****************************************************************************
1024 Reply to a write and X (async reply)
1025 ****************************************************************************/
1026 static void reply_write_and_X_send(struct ntvfs_request
*ntvfs
)
1028 struct smbsrv_request
*req
;
1029 union smb_write
*io
;
1031 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
1033 /* construct reply */
1034 smbsrv_setup_reply(req
, 6, 0);
1036 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1037 SSVAL(req
->out
.vwv
, VWV(1), 0);
1038 SSVAL(req
->out
.vwv
, VWV(2), io
->writex
.out
.nwritten
& 0xFFFF);
1039 SSVAL(req
->out
.vwv
, VWV(3), io
->writex
.out
.remaining
);
1040 SSVAL(req
->out
.vwv
, VWV(4), io
->writex
.out
.nwritten
>> 16);
1041 SMBSRV_VWV_RESERVED(5, 1);
1043 smbsrv_chain_reply(req
);
1046 /****************************************************************************
1047 Reply to a write and X.
1048 ****************************************************************************/
1049 void smbsrv_reply_write_and_X(struct smbsrv_request
*req
)
1051 union smb_write
*io
;
1053 if (req
->in
.wct
!= 14) {
1054 SMBSRV_CHECK_WCT(req
, 12);
1057 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1058 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1060 io
->writex
.level
= RAW_WRITE_WRITEX
;
1061 io
->writex
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
1062 io
->writex
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1063 io
->writex
.in
.wmode
= SVAL(req
->in
.vwv
, VWV(7));
1064 io
->writex
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(8));
1065 io
->writex
.in
.count
= SVAL(req
->in
.vwv
, VWV(10));
1066 io
->writex
.in
.data
= req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(11));
1068 if (req
->in
.wct
== 14) {
1069 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(12));
1070 uint16_t count_high
= SVAL(req
->in
.vwv
, VWV(9));
1071 io
->writex
.in
.offset
|= (((uint64_t)offset_high
) << 32);
1072 io
->writex
.in
.count
|= ((uint32_t)count_high
) << 16;
1075 /* make sure the data is in bounds */
1076 if (req_data_oob(&req
->in
.bufinfo
, io
->writex
.in
.data
, io
->writex
.in
.count
)) {
1077 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
1081 SMBSRV_CHECK_FILE_HANDLE(io
->writex
.in
.file
.ntvfs
);
1082 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1086 /****************************************************************************
1087 Reply to a lseek (async reply)
1088 ****************************************************************************/
1089 static void reply_lseek_send(struct ntvfs_request
*ntvfs
)
1091 struct smbsrv_request
*req
;
1094 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_seek
);
1096 /* construct reply */
1097 smbsrv_setup_reply(req
, 2, 0);
1099 SIVALS(req
->out
.vwv
, VWV(0), io
->lseek
.out
.offset
);
1101 smbsrv_send_reply(req
);
1104 /****************************************************************************
1106 ****************************************************************************/
1107 void smbsrv_reply_lseek(struct smbsrv_request
*req
)
1111 SMBSRV_CHECK_WCT(req
, 4);
1112 SMBSRV_TALLOC_IO_PTR(io
, union smb_seek
);
1113 SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1115 io
->lseek
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1116 io
->lseek
.in
.mode
= SVAL(req
->in
.vwv
, VWV(1));
1117 io
->lseek
.in
.offset
= IVALS(req
->in
.vwv
, VWV(2));
1119 SMBSRV_CHECK_FILE_HANDLE(io
->lseek
.in
.file
.ntvfs
);
1120 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req
->ntvfs
, io
));
1123 /****************************************************************************
1125 ****************************************************************************/
1126 void smbsrv_reply_flush(struct smbsrv_request
*req
)
1128 union smb_flush
*io
;
1132 SMBSRV_CHECK_WCT(req
, 1);
1133 SMBSRV_TALLOC_IO_PTR(io
, union smb_flush
);
1134 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1136 fnum
= SVAL(req
->in
.vwv
, VWV(0));
1137 if (fnum
== 0xFFFF) {
1138 io
->flush_all
.level
= RAW_FLUSH_ALL
;
1140 io
->flush
.level
= RAW_FLUSH_FLUSH
;
1141 io
->flush
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1142 SMBSRV_CHECK_FILE_HANDLE(io
->flush
.in
.file
.ntvfs
);
1145 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req
->ntvfs
, io
));
1148 /****************************************************************************
1151 Note that this has to deal with closing a directory opened by NT SMB's.
1152 ****************************************************************************/
1153 void smbsrv_reply_close(struct smbsrv_request
*req
)
1155 union smb_close
*io
;
1158 SMBSRV_CHECK_WCT(req
, 3);
1159 SMBSRV_TALLOC_IO_PTR(io
, union smb_close
);
1160 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1162 io
->close
.level
= RAW_CLOSE_CLOSE
;
1163 io
->close
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1164 io
->close
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
1166 SMBSRV_CHECK_FILE_HANDLE(io
->close
.in
.file
.ntvfs
);
1167 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req
->ntvfs
, io
));
1171 /****************************************************************************
1172 Reply to a writeclose (async reply)
1173 ****************************************************************************/
1174 static void reply_writeclose_send(struct ntvfs_request
*ntvfs
)
1176 struct smbsrv_request
*req
;
1177 union smb_write
*io
;
1179 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
1181 /* construct reply */
1182 smbsrv_setup_reply(req
, 1, 0);
1184 SSVAL(req
->out
.vwv
, VWV(0), io
->write
.out
.nwritten
);
1186 smbsrv_send_reply(req
);
1189 /****************************************************************************
1190 Reply to a writeclose (Core+ protocol).
1191 ****************************************************************************/
1192 void smbsrv_reply_writeclose(struct smbsrv_request
*req
)
1194 union smb_write
*io
;
1196 /* this one is pretty weird - the wct can be 6 or 12 */
1197 if (req
->in
.wct
!= 12) {
1198 SMBSRV_CHECK_WCT(req
, 6);
1201 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1202 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1204 io
->writeclose
.level
= RAW_WRITE_WRITECLOSE
;
1205 io
->writeclose
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1206 io
->writeclose
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
1207 io
->writeclose
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
1208 io
->writeclose
.in
.mtime
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(4));
1209 io
->writeclose
.in
.data
= req
->in
.data
+ 1;
1211 /* make sure they gave us the data they promised */
1212 if (req_data_oob(&req
->in
.bufinfo
, io
->writeclose
.in
.data
, io
->writeclose
.in
.count
)) {
1213 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1217 SMBSRV_CHECK_FILE_HANDLE(io
->writeclose
.in
.file
.ntvfs
);
1218 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1221 /****************************************************************************
1223 ****************************************************************************/
1224 void smbsrv_reply_lock(struct smbsrv_request
*req
)
1226 union smb_lock
*lck
;
1229 SMBSRV_CHECK_WCT(req
, 5);
1230 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1231 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1233 lck
->lock
.level
= RAW_LOCK_LOCK
;
1234 lck
->lock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1235 lck
->lock
.in
.count
= IVAL(req
->in
.vwv
, VWV(1));
1236 lck
->lock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1238 SMBSRV_CHECK_FILE_HANDLE(lck
->lock
.in
.file
.ntvfs
);
1239 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1243 /****************************************************************************
1245 ****************************************************************************/
1246 void smbsrv_reply_unlock(struct smbsrv_request
*req
)
1248 union smb_lock
*lck
;
1251 SMBSRV_CHECK_WCT(req
, 5);
1252 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1253 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1255 lck
->unlock
.level
= RAW_LOCK_UNLOCK
;
1256 lck
->unlock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1257 lck
->unlock
.in
.count
= IVAL(req
->in
.vwv
, VWV(1));
1258 lck
->unlock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1260 SMBSRV_CHECK_FILE_HANDLE(lck
->unlock
.in
.file
.ntvfs
);
1261 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1265 /****************************************************************************
1267 ****************************************************************************/
1268 void smbsrv_reply_tdis(struct smbsrv_request
*req
)
1270 struct smbsrv_handle
*h
, *nh
;
1272 SMBSRV_CHECK_WCT(req
, 0);
1275 * TODO: cancel all pending requests on this tcon
1279 * close all handles on this tcon
1281 for (h
=req
->tcon
->handles
.list
; h
; h
=nh
) {
1286 /* finally destroy the tcon */
1287 talloc_free(req
->tcon
);
1290 smbsrv_setup_reply(req
, 0, 0);
1291 smbsrv_send_reply(req
);
1295 /****************************************************************************
1296 Reply to a echo. This is one of the few calls that is handled directly (the
1297 backends don't see it at all)
1298 ****************************************************************************/
1299 void smbsrv_reply_echo(struct smbsrv_request
*req
)
1304 SMBSRV_CHECK_WCT(req
, 1);
1306 count
= SVAL(req
->in
.vwv
, VWV(0));
1308 smbsrv_setup_reply(req
, 1, req
->in
.data_size
);
1310 memcpy(req
->out
.data
, req
->in
.data
, req
->in
.data_size
);
1312 for (i
=1; i
<= count
;i
++) {
1313 struct smbsrv_request
*this_req
;
1316 this_req
= smbsrv_setup_secondary_request(req
);
1321 SSVAL(this_req
->out
.vwv
, VWV(0), i
);
1322 smbsrv_send_reply(this_req
);
1328 /****************************************************************************
1329 Reply to a printopen (async reply)
1330 ****************************************************************************/
1331 static void reply_printopen_send(struct ntvfs_request
*ntvfs
)
1333 struct smbsrv_request
*req
;
1336 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
1338 /* construct reply */
1339 smbsrv_setup_reply(req
, 1, 0);
1341 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->openold
.out
.file
.ntvfs
);
1343 smbsrv_send_reply(req
);
1346 /****************************************************************************
1347 Reply to a printopen.
1348 ****************************************************************************/
1349 void smbsrv_reply_printopen(struct smbsrv_request
*req
)
1354 SMBSRV_CHECK_WCT(req
, 2);
1355 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
1356 SMBSRV_SETUP_NTVFS_REQUEST(reply_printopen_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1358 oi
->splopen
.level
= RAW_OPEN_SPLOPEN
;
1359 oi
->splopen
.in
.setup_length
= SVAL(req
->in
.vwv
, VWV(0));
1360 oi
->splopen
.in
.mode
= SVAL(req
->in
.vwv
, VWV(1));
1362 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->splopen
.in
.ident
, req
->in
.data
, STR_TERMINATE
);
1364 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
1367 /****************************************************************************
1368 Reply to a printclose.
1369 ****************************************************************************/
1370 void smbsrv_reply_printclose(struct smbsrv_request
*req
)
1372 union smb_close
*io
;
1375 SMBSRV_CHECK_WCT(req
, 3);
1376 SMBSRV_TALLOC_IO_PTR(io
, union smb_close
);
1377 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1379 io
->splclose
.level
= RAW_CLOSE_SPLCLOSE
;
1380 io
->splclose
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1382 SMBSRV_CHECK_FILE_HANDLE(io
->splclose
.in
.file
.ntvfs
);
1383 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req
->ntvfs
, io
));
1386 /****************************************************************************
1387 Reply to a printqueue.
1388 ****************************************************************************/
1389 static void reply_printqueue_send(struct ntvfs_request
*ntvfs
)
1391 struct smbsrv_request
*req
;
1394 const unsigned int el_size
= 28;
1396 SMBSRV_CHECK_ASYNC_STATUS(lpq
,union smb_lpq
);
1398 /* construct reply */
1399 smbsrv_setup_reply(req
, 2, 0);
1401 /* truncate the returned list to fit in the negotiated buffer size */
1402 maxcount
= (req_max_data(req
) - 3) / el_size
;
1403 if (maxcount
< lpq
->retq
.out
.count
) {
1404 lpq
->retq
.out
.count
= maxcount
;
1407 /* setup enough space in the reply */
1408 req_grow_data(req
, 3 + el_size
*lpq
->retq
.out
.count
);
1410 /* and fill it in */
1411 SSVAL(req
->out
.vwv
, VWV(0), lpq
->retq
.out
.count
);
1412 SSVAL(req
->out
.vwv
, VWV(1), lpq
->retq
.out
.restart_idx
);
1414 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
1415 SSVAL(req
->out
.data
, 1, el_size
*lpq
->retq
.out
.count
);
1417 req
->out
.ptr
= req
->out
.data
+ 3;
1419 for (i
=0;i
<lpq
->retq
.out
.count
;i
++) {
1420 srv_push_dos_date2(req
->smb_conn
, req
->out
.ptr
, 0 , lpq
->retq
.out
.queue
[i
].time
);
1421 SCVAL(req
->out
.ptr
, 4, lpq
->retq
.out
.queue
[i
].status
);
1422 SSVAL(req
->out
.ptr
, 5, lpq
->retq
.out
.queue
[i
].job
);
1423 SIVAL(req
->out
.ptr
, 7, lpq
->retq
.out
.queue
[i
].size
);
1424 SCVAL(req
->out
.ptr
, 11, 0); /* reserved */
1425 req_push_str(req
, req
->out
.ptr
+12, lpq
->retq
.out
.queue
[i
].user
, 16, STR_ASCII
);
1426 req
->out
.ptr
+= el_size
;
1429 smbsrv_send_reply(req
);
1432 /****************************************************************************
1433 Reply to a printqueue.
1434 ****************************************************************************/
1435 void smbsrv_reply_printqueue(struct smbsrv_request
*req
)
1440 SMBSRV_CHECK_WCT(req
, 2);
1441 SMBSRV_TALLOC_IO_PTR(lpq
, union smb_lpq
);
1442 SMBSRV_SETUP_NTVFS_REQUEST(reply_printqueue_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1444 lpq
->retq
.level
= RAW_LPQ_RETQ
;
1445 lpq
->retq
.in
.maxcount
= SVAL(req
->in
.vwv
, VWV(0));
1446 lpq
->retq
.in
.startidx
= SVAL(req
->in
.vwv
, VWV(1));
1448 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lpq(req
->ntvfs
, lpq
));
1452 /****************************************************************************
1453 Reply to a printwrite.
1454 ****************************************************************************/
1455 void smbsrv_reply_printwrite(struct smbsrv_request
*req
)
1457 union smb_write
*io
;
1460 SMBSRV_CHECK_WCT(req
, 1);
1461 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1462 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1464 if (req
->in
.data_size
< 3) {
1465 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1469 io
->splwrite
.level
= RAW_WRITE_SPLWRITE
;
1470 io
->splwrite
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1471 io
->splwrite
.in
.count
= SVAL(req
->in
.data
, 1);
1472 io
->splwrite
.in
.data
= req
->in
.data
+ 3;
1474 /* make sure they gave us the data they promised */
1475 if (req_data_oob(&req
->in
.bufinfo
, io
->splwrite
.in
.data
, io
->splwrite
.in
.count
)) {
1476 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1480 SMBSRV_CHECK_FILE_HANDLE(io
->splwrite
.in
.file
.ntvfs
);
1481 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1485 /****************************************************************************
1487 ****************************************************************************/
1488 void smbsrv_reply_mkdir(struct smbsrv_request
*req
)
1490 union smb_mkdir
*io
;
1492 /* parse the request */
1493 SMBSRV_CHECK_WCT(req
, 0);
1494 SMBSRV_TALLOC_IO_PTR(io
, union smb_mkdir
);
1495 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1497 io
->generic
.level
= RAW_MKDIR_MKDIR
;
1498 req_pull_ascii4(&req
->in
.bufinfo
, &io
->mkdir
.in
.path
, req
->in
.data
, STR_TERMINATE
);
1500 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_mkdir(req
->ntvfs
, io
));
1504 /****************************************************************************
1506 ****************************************************************************/
1507 void smbsrv_reply_rmdir(struct smbsrv_request
*req
)
1509 struct smb_rmdir
*io
;
1511 /* parse the request */
1512 SMBSRV_CHECK_WCT(req
, 0);
1513 SMBSRV_TALLOC_IO_PTR(io
, struct smb_rmdir
);
1514 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1516 req_pull_ascii4(&req
->in
.bufinfo
, &io
->in
.path
, req
->in
.data
, STR_TERMINATE
);
1518 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rmdir(req
->ntvfs
, io
));
1522 /****************************************************************************
1524 ****************************************************************************/
1525 void smbsrv_reply_mv(struct smbsrv_request
*req
)
1527 union smb_rename
*io
;
1530 /* parse the request */
1531 SMBSRV_CHECK_WCT(req
, 1);
1532 SMBSRV_TALLOC_IO_PTR(io
, union smb_rename
);
1533 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1535 io
->generic
.level
= RAW_RENAME_RENAME
;
1536 io
->rename
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
1539 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->rename
.in
.pattern1
, p
, STR_TERMINATE
);
1540 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->rename
.in
.pattern2
, p
, STR_TERMINATE
);
1542 if (!io
->rename
.in
.pattern1
|| !io
->rename
.in
.pattern2
) {
1543 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1547 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req
->ntvfs
, io
));
1551 /****************************************************************************
1552 Reply to an NT rename.
1553 ****************************************************************************/
1554 void smbsrv_reply_ntrename(struct smbsrv_request
*req
)
1556 union smb_rename
*io
;
1559 /* parse the request */
1560 SMBSRV_CHECK_WCT(req
, 4);
1561 SMBSRV_TALLOC_IO_PTR(io
, union smb_rename
);
1562 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1564 io
->generic
.level
= RAW_RENAME_NTRENAME
;
1565 io
->ntrename
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
1566 io
->ntrename
.in
.flags
= SVAL(req
->in
.vwv
, VWV(1));
1567 io
->ntrename
.in
.cluster_size
= IVAL(req
->in
.vwv
, VWV(2));
1570 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->ntrename
.in
.old_name
, p
, STR_TERMINATE
);
1571 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->ntrename
.in
.new_name
, p
, STR_TERMINATE
);
1573 if (!io
->ntrename
.in
.old_name
|| !io
->ntrename
.in
.new_name
) {
1574 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1578 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req
->ntvfs
, io
));
1581 /****************************************************************************
1582 Reply to a file copy (async reply)
1583 ****************************************************************************/
1584 static void reply_copy_send(struct ntvfs_request
*ntvfs
)
1586 struct smbsrv_request
*req
;
1587 struct smb_copy
*cp
;
1589 SMBSRV_CHECK_ASYNC_STATUS(cp
, struct smb_copy
);
1591 /* build the reply */
1592 smbsrv_setup_reply(req
, 1, 0);
1594 SSVAL(req
->out
.vwv
, VWV(0), cp
->out
.count
);
1596 smbsrv_send_reply(req
);
1599 /****************************************************************************
1600 Reply to a file copy.
1601 ****************************************************************************/
1602 void smbsrv_reply_copy(struct smbsrv_request
*req
)
1604 struct smb_copy
*cp
;
1608 SMBSRV_CHECK_WCT(req
, 3);
1609 SMBSRV_TALLOC_IO_PTR(cp
, struct smb_copy
);
1610 SMBSRV_SETUP_NTVFS_REQUEST(reply_copy_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1612 cp
->in
.tid2
= SVAL(req
->in
.vwv
, VWV(0));
1613 cp
->in
.ofun
= SVAL(req
->in
.vwv
, VWV(1));
1614 cp
->in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
1617 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &cp
->in
.path1
, p
, STR_TERMINATE
);
1618 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &cp
->in
.path2
, p
, STR_TERMINATE
);
1620 if (!cp
->in
.path1
|| !cp
->in
.path2
) {
1621 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1625 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_copy(req
->ntvfs
, cp
));
1628 /****************************************************************************
1629 Reply to a lockingX request (async send)
1630 ****************************************************************************/
1631 static void reply_lockingX_send(struct ntvfs_request
*ntvfs
)
1633 struct smbsrv_request
*req
;
1634 union smb_lock
*lck
;
1636 SMBSRV_CHECK_ASYNC_STATUS(lck
, union smb_lock
);
1638 /* if it was an oplock break ack then we only send a reply if
1639 there was an error */
1640 if (lck
->lockx
.in
.ulock_cnt
+ lck
->lockx
.in
.lock_cnt
== 0) {
1645 /* construct reply */
1646 smbsrv_setup_reply(req
, 2, 0);
1648 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1649 SSVAL(req
->out
.vwv
, VWV(1), 0);
1651 smbsrv_chain_reply(req
);
1655 /****************************************************************************
1656 Reply to a lockingX request.
1657 ****************************************************************************/
1658 void smbsrv_reply_lockingX(struct smbsrv_request
*req
)
1660 union smb_lock
*lck
;
1661 unsigned int total_locks
, i
;
1662 unsigned int lck_size
;
1666 SMBSRV_CHECK_WCT(req
, 8);
1667 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1668 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1670 lck
->lockx
.level
= RAW_LOCK_LOCKX
;
1671 lck
->lockx
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
1672 lck
->lockx
.in
.mode
= SVAL(req
->in
.vwv
, VWV(3));
1673 lck
->lockx
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(4));
1674 lck
->lockx
.in
.ulock_cnt
= SVAL(req
->in
.vwv
, VWV(6));
1675 lck
->lockx
.in
.lock_cnt
= SVAL(req
->in
.vwv
, VWV(7));
1677 total_locks
= lck
->lockx
.in
.ulock_cnt
+ lck
->lockx
.in
.lock_cnt
;
1679 /* there are two variants, one with 64 bit offsets and counts */
1680 if (lck
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
1686 /* make sure we got the promised data */
1687 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, total_locks
* lck_size
)) {
1688 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1692 /* allocate the locks array */
1694 lck
->lockx
.in
.locks
= talloc_array(req
, struct smb_lock_entry
,
1696 if (lck
->lockx
.in
.locks
== NULL
) {
1697 smbsrv_send_error(req
, NT_STATUS_NO_MEMORY
);
1704 /* construct the locks array */
1705 for (i
=0;i
<total_locks
;i
++) {
1706 uint32_t ofs_high
=0, count_high
=0;
1708 lck
->lockx
.in
.locks
[i
].pid
= SVAL(p
, 0);
1710 if (lck
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
1711 ofs_high
= IVAL(p
, 4);
1712 lck
->lockx
.in
.locks
[i
].offset
= IVAL(p
, 8);
1713 count_high
= IVAL(p
, 12);
1714 lck
->lockx
.in
.locks
[i
].count
= IVAL(p
, 16);
1716 lck
->lockx
.in
.locks
[i
].offset
= IVAL(p
, 2);
1717 lck
->lockx
.in
.locks
[i
].count
= IVAL(p
, 6);
1719 if (ofs_high
!= 0 || count_high
!= 0) {
1720 lck
->lockx
.in
.locks
[i
].count
|= ((uint64_t)count_high
) << 32;
1721 lck
->lockx
.in
.locks
[i
].offset
|= ((uint64_t)ofs_high
) << 32;
1726 SMBSRV_CHECK_FILE_HANDLE(lck
->lockx
.in
.file
.ntvfs
);
1727 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1730 /****************************************************************************
1731 Reply to a SMBreadbmpx (read block multiplex) request.
1732 ****************************************************************************/
1733 void smbsrv_reply_readbmpx(struct smbsrv_request
*req
)
1735 /* tell the client to not use a multiplexed read - its too broken to use */
1736 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1740 /****************************************************************************
1741 Reply to a SMBsetattrE.
1742 ****************************************************************************/
1743 void smbsrv_reply_setattrE(struct smbsrv_request
*req
)
1745 union smb_setfileinfo
*info
;
1748 SMBSRV_CHECK_WCT(req
, 7);
1749 SMBSRV_TALLOC_IO_PTR(info
, union smb_setfileinfo
);
1750 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1752 info
->setattre
.level
= RAW_SFILEINFO_SETATTRE
;
1753 info
->setattre
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1754 info
->setattre
.in
.create_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
1755 info
->setattre
.in
.access_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(3));
1756 info
->setattre
.in
.write_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(5));
1758 SMBSRV_CHECK_FILE_HANDLE(info
->setattre
.in
.file
.ntvfs
);
1759 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req
->ntvfs
, info
));
1763 /****************************************************************************
1764 Reply to a SMBwritebmpx (write block multiplex primary) request.
1765 ****************************************************************************/
1766 void smbsrv_reply_writebmpx(struct smbsrv_request
*req
)
1768 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1772 /****************************************************************************
1773 Reply to a SMBwritebs (write block multiplex secondary) request.
1774 ****************************************************************************/
1775 void smbsrv_reply_writebs(struct smbsrv_request
*req
)
1777 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1782 /****************************************************************************
1783 Reply to a SMBgetattrE (async reply)
1784 ****************************************************************************/
1785 static void reply_getattrE_send(struct ntvfs_request
*ntvfs
)
1787 struct smbsrv_request
*req
;
1788 union smb_fileinfo
*info
;
1790 SMBSRV_CHECK_ASYNC_STATUS(info
, union smb_fileinfo
);
1793 smbsrv_setup_reply(req
, 11, 0);
1795 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(0), info
->getattre
.out
.create_time
);
1796 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(2), info
->getattre
.out
.access_time
);
1797 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(4), info
->getattre
.out
.write_time
);
1798 SIVAL(req
->out
.vwv
, VWV(6), info
->getattre
.out
.size
);
1799 SIVAL(req
->out
.vwv
, VWV(8), info
->getattre
.out
.alloc_size
);
1800 SSVAL(req
->out
.vwv
, VWV(10), info
->getattre
.out
.attrib
);
1802 smbsrv_send_reply(req
);
1805 /****************************************************************************
1806 Reply to a SMBgetattrE.
1807 ****************************************************************************/
1808 void smbsrv_reply_getattrE(struct smbsrv_request
*req
)
1810 union smb_fileinfo
*info
;
1813 SMBSRV_CHECK_WCT(req
, 1);
1814 SMBSRV_TALLOC_IO_PTR(info
, union smb_fileinfo
);
1815 SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1817 info
->getattr
.level
= RAW_FILEINFO_GETATTRE
;
1818 info
->getattr
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1820 SMBSRV_CHECK_FILE_HANDLE(info
->getattr
.in
.file
.ntvfs
);
1821 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req
->ntvfs
, info
));
1824 void smbsrv_reply_sesssetup_send(struct smbsrv_request
*req
,
1825 union smb_sesssetup
*io
,
1828 switch (io
->old
.level
) {
1829 case RAW_SESSSETUP_OLD
:
1830 if (!NT_STATUS_IS_OK(status
)) {
1831 smbsrv_send_error(req
, status
);
1835 /* construct reply */
1836 smbsrv_setup_reply(req
, 3, 0);
1838 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1839 SSVAL(req
->out
.vwv
, VWV(1), 0);
1840 SSVAL(req
->out
.vwv
, VWV(2), io
->old
.out
.action
);
1842 SSVAL(req
->out
.hdr
, HDR_UID
, io
->old
.out
.vuid
);
1844 smbsrv_chain_reply(req
);
1847 case RAW_SESSSETUP_NT1
:
1848 if (!NT_STATUS_IS_OK(status
)) {
1849 smbsrv_send_error(req
, status
);
1853 /* construct reply */
1854 smbsrv_setup_reply(req
, 3, 0);
1856 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1857 SSVAL(req
->out
.vwv
, VWV(1), 0);
1858 SSVAL(req
->out
.vwv
, VWV(2), io
->nt1
.out
.action
);
1860 SSVAL(req
->out
.hdr
, HDR_UID
, io
->nt1
.out
.vuid
);
1862 req_push_str(req
, NULL
, io
->nt1
.out
.os
, -1, STR_TERMINATE
);
1863 req_push_str(req
, NULL
, io
->nt1
.out
.lanman
, -1, STR_TERMINATE
);
1864 req_push_str(req
, NULL
, io
->nt1
.out
.domain
, -1, STR_TERMINATE
);
1866 smbsrv_chain_reply(req
);
1869 case RAW_SESSSETUP_SPNEGO
:
1870 if (!NT_STATUS_IS_OK(status
) &&
1871 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1872 smbsrv_send_error(req
, status
);
1876 /* construct reply */
1877 smbsrv_setup_reply(req
, 4, io
->spnego
.out
.secblob
.length
);
1879 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1880 smbsrv_setup_error(req
, status
);
1883 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1884 SSVAL(req
->out
.vwv
, VWV(1), 0);
1885 SSVAL(req
->out
.vwv
, VWV(2), io
->spnego
.out
.action
);
1886 SSVAL(req
->out
.vwv
, VWV(3), io
->spnego
.out
.secblob
.length
);
1888 SSVAL(req
->out
.hdr
, HDR_UID
, io
->spnego
.out
.vuid
);
1890 memcpy(req
->out
.data
, io
->spnego
.out
.secblob
.data
, io
->spnego
.out
.secblob
.length
);
1891 req_push_str(req
, NULL
, io
->spnego
.out
.os
, -1, STR_TERMINATE
);
1892 req_push_str(req
, NULL
, io
->spnego
.out
.lanman
, -1, STR_TERMINATE
);
1893 req_push_str(req
, NULL
, io
->spnego
.out
.workgroup
, -1, STR_TERMINATE
);
1895 smbsrv_chain_reply(req
);
1898 case RAW_SESSSETUP_SMB2
:
1902 smbsrv_send_error(req
, NT_STATUS_INTERNAL_ERROR
);
1905 /****************************************************************************
1906 reply to an old style session setup command
1907 ****************************************************************************/
1908 static void reply_sesssetup_old(struct smbsrv_request
*req
)
1912 union smb_sesssetup
*io
;
1914 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
1916 io
->old
.level
= RAW_SESSSETUP_OLD
;
1919 io
->old
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
1920 io
->old
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
1921 io
->old
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
1922 io
->old
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
1923 passlen
= SVAL(req
->in
.vwv
, VWV(7));
1925 /* check the request isn't malformed */
1926 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, passlen
)) {
1927 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1932 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen
, &io
->old
.in
.password
)) {
1933 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1938 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.user
, p
, -1, STR_TERMINATE
);
1939 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.domain
, p
, -1, STR_TERMINATE
);
1940 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.os
, p
, -1, STR_TERMINATE
);
1941 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.lanman
, p
, -1, STR_TERMINATE
);
1943 /* call the generic handler */
1944 smbsrv_sesssetup_backend(req
, io
);
1947 /****************************************************************************
1948 reply to an NT1 style session setup command
1949 ****************************************************************************/
1950 static void reply_sesssetup_nt1(struct smbsrv_request
*req
)
1953 uint16_t passlen1
, passlen2
;
1954 union smb_sesssetup
*io
;
1956 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
1958 io
->nt1
.level
= RAW_SESSSETUP_NT1
;
1961 io
->nt1
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
1962 io
->nt1
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
1963 io
->nt1
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
1964 io
->nt1
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
1965 passlen1
= SVAL(req
->in
.vwv
, VWV(7));
1966 passlen2
= SVAL(req
->in
.vwv
, VWV(8));
1967 io
->nt1
.in
.capabilities
= IVAL(req
->in
.vwv
, VWV(11));
1969 /* check the request isn't malformed */
1970 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, passlen1
) ||
1971 req_data_oob(&req
->in
.bufinfo
, req
->in
.data
+ passlen1
, passlen2
)) {
1972 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1977 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen1
, &io
->nt1
.in
.password1
)) {
1978 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1982 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen2
, &io
->nt1
.in
.password2
)) {
1983 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1988 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.user
, p
, -1, STR_TERMINATE
);
1989 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.domain
, p
, -1, STR_TERMINATE
);
1990 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.os
, p
, -1, STR_TERMINATE
);
1991 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.lanman
, p
, -1, STR_TERMINATE
);
1993 /* call the generic handler */
1994 smbsrv_sesssetup_backend(req
, io
);
1998 /****************************************************************************
1999 reply to an SPNEGO style session setup command
2000 ****************************************************************************/
2001 static void reply_sesssetup_spnego(struct smbsrv_request
*req
)
2005 union smb_sesssetup
*io
;
2007 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
2009 io
->spnego
.level
= RAW_SESSSETUP_SPNEGO
;
2012 io
->spnego
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
2013 io
->spnego
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
2014 io
->spnego
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
2015 io
->spnego
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
2016 blob_len
= SVAL(req
->in
.vwv
, VWV(7));
2017 io
->spnego
.in
.capabilities
= IVAL(req
->in
.vwv
, VWV(10));
2020 if (!req_pull_blob(&req
->in
.bufinfo
, p
, blob_len
, &io
->spnego
.in
.secblob
)) {
2021 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2026 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.os
, p
, -1, STR_TERMINATE
);
2027 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.lanman
, p
, -1, STR_TERMINATE
);
2028 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.workgroup
, p
, -1, STR_TERMINATE
);
2030 /* call the generic handler */
2031 smbsrv_sesssetup_backend(req
, io
);
2035 /****************************************************************************
2036 reply to a session setup command
2037 ****************************************************************************/
2038 void smbsrv_reply_sesssetup(struct smbsrv_request
*req
)
2040 switch (req
->in
.wct
) {
2042 /* a pre-NT1 call */
2043 reply_sesssetup_old(req
);
2047 reply_sesssetup_nt1(req
);
2051 reply_sesssetup_spnego(req
);
2055 /* unsupported variant */
2056 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2059 /****************************************************************************
2060 Reply to a exit. This closes all files open by a smbpid
2061 ****************************************************************************/
2062 void smbsrv_reply_exit(struct smbsrv_request
*req
)
2064 struct smbsrv_handle_session_item
*i
, *ni
;
2065 struct smbsrv_handle
*h
;
2066 struct smbsrv_tcon
*tcon
;
2069 SMBSRV_CHECK_WCT(req
, 0);
2071 smbpid
= SVAL(req
->in
.hdr
,HDR_PID
);
2073 /* first destroy all handles, which have the same PID as the request */
2074 for (i
=req
->session
->handles
; i
; i
=ni
) {
2077 if (h
->smbpid
!= smbpid
) continue;
2083 * then let the ntvfs backends proxy the call if they want to,
2084 * but we didn't check the return value of the backends,
2085 * as for the SMB client the call succeed
2087 for (tcon
=req
->smb_conn
->smb_tcons
.list
;tcon
;tcon
=tcon
->next
) {
2089 SMBSRV_SETUP_NTVFS_REQUEST(NULL
,0);
2090 ntvfs_exit(req
->ntvfs
);
2091 talloc_free(req
->ntvfs
);
2096 smbsrv_setup_reply(req
, 0, 0);
2097 smbsrv_send_reply(req
);
2100 /****************************************************************************
2101 Reply to a SMBulogoffX.
2102 ****************************************************************************/
2103 void smbsrv_reply_ulogoffX(struct smbsrv_request
*req
)
2105 struct smbsrv_handle_session_item
*i
, *ni
;
2106 struct smbsrv_handle
*h
;
2107 struct smbsrv_tcon
*tcon
;
2109 SMBSRV_CHECK_WCT(req
, 2);
2112 * TODO: cancel all pending requests
2116 /* destroy all handles */
2117 for (i
=req
->session
->handles
; i
; i
=ni
) {
2124 * then let the ntvfs backends proxy the call if they want to,
2125 * but we didn't check the return value of the backends,
2126 * as for the SMB client the call succeed
2128 for (tcon
=req
->smb_conn
->smb_tcons
.list
;tcon
;tcon
=tcon
->next
) {
2130 SMBSRV_SETUP_NTVFS_REQUEST(NULL
,0);
2131 ntvfs_logoff(req
->ntvfs
);
2132 talloc_free(req
->ntvfs
);
2137 talloc_free(req
->session
);
2138 req
->session
= NULL
; /* it is now invalid, don't use on
2139 any chained packets */
2141 smbsrv_setup_reply(req
, 2, 0);
2143 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
2144 SSVAL(req
->out
.vwv
, VWV(1), 0);
2146 smbsrv_chain_reply(req
);
2149 /****************************************************************************
2150 Reply to an SMBfindclose request
2151 ****************************************************************************/
2152 void smbsrv_reply_findclose(struct smbsrv_request
*req
)
2154 union smb_search_close
*io
;
2157 SMBSRV_CHECK_WCT(req
, 1);
2158 SMBSRV_TALLOC_IO_PTR(io
, union smb_search_close
);
2159 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
2161 io
->findclose
.level
= RAW_FINDCLOSE_FINDCLOSE
;
2162 io
->findclose
.in
.handle
= SVAL(req
->in
.vwv
, VWV(0));
2164 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req
->ntvfs
, io
));
2167 /****************************************************************************
2168 Reply to an SMBfindnclose request
2169 ****************************************************************************/
2170 void smbsrv_reply_findnclose(struct smbsrv_request
*req
)
2172 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2176 /****************************************************************************
2177 Reply to an SMBntcreateX request (async send)
2178 ****************************************************************************/
2179 static void reply_ntcreate_and_X_send(struct ntvfs_request
*ntvfs
)
2181 struct smbsrv_request
*req
;
2184 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_open
);
2186 /* construct reply */
2187 smbsrv_setup_reply(req
, 34, 0);
2189 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
2190 SSVAL(req
->out
.vwv
, VWV(1), 0);
2191 SCVAL(req
->out
.vwv
, VWV(2), io
->ntcreatex
.out
.oplock_level
);
2193 /* the rest of the parameters are not aligned! */
2194 smbsrv_push_fnum(req
->out
.vwv
, 5, io
->ntcreatex
.out
.file
.ntvfs
);
2195 SIVAL(req
->out
.vwv
, 7, io
->ntcreatex
.out
.create_action
);
2196 push_nttime(req
->out
.vwv
, 11, io
->ntcreatex
.out
.create_time
);
2197 push_nttime(req
->out
.vwv
, 19, io
->ntcreatex
.out
.access_time
);
2198 push_nttime(req
->out
.vwv
, 27, io
->ntcreatex
.out
.write_time
);
2199 push_nttime(req
->out
.vwv
, 35, io
->ntcreatex
.out
.change_time
);
2200 SIVAL(req
->out
.vwv
, 43, io
->ntcreatex
.out
.attrib
);
2201 SBVAL(req
->out
.vwv
, 47, io
->ntcreatex
.out
.alloc_size
);
2202 SBVAL(req
->out
.vwv
, 55, io
->ntcreatex
.out
.size
);
2203 SSVAL(req
->out
.vwv
, 63, io
->ntcreatex
.out
.file_type
);
2204 SSVAL(req
->out
.vwv
, 65, io
->ntcreatex
.out
.ipc_state
);
2205 SCVAL(req
->out
.vwv
, 67, io
->ntcreatex
.out
.is_directory
);
2207 req
->chained_fnum
= SVAL(req
->out
.vwv
, 5);
2209 smbsrv_chain_reply(req
);
2212 /****************************************************************************
2213 Reply to an SMBntcreateX request
2214 ****************************************************************************/
2215 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request
*req
)
2220 /* parse the request */
2221 SMBSRV_CHECK_WCT(req
, 24);
2222 SMBSRV_TALLOC_IO_PTR(io
, union smb_open
);
2223 SMBSRV_SETUP_NTVFS_REQUEST(reply_ntcreate_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
2225 io
->ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
2227 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2228 fname_len
= SVAL(req
->in
.vwv
, 5);
2229 io
->ntcreatex
.in
.flags
= IVAL(req
->in
.vwv
, 7);
2230 io
->ntcreatex
.in
.root_fid
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, 11);
2231 io
->ntcreatex
.in
.access_mask
= IVAL(req
->in
.vwv
, 15);
2232 io
->ntcreatex
.in
.alloc_size
= BVAL(req
->in
.vwv
, 19);
2233 io
->ntcreatex
.in
.file_attr
= IVAL(req
->in
.vwv
, 27);
2234 io
->ntcreatex
.in
.share_access
= IVAL(req
->in
.vwv
, 31);
2235 io
->ntcreatex
.in
.open_disposition
= IVAL(req
->in
.vwv
, 35);
2236 io
->ntcreatex
.in
.create_options
= IVAL(req
->in
.vwv
, 39);
2237 io
->ntcreatex
.in
.impersonation
= IVAL(req
->in
.vwv
, 43);
2238 io
->ntcreatex
.in
.security_flags
= CVAL(req
->in
.vwv
, 47);
2239 io
->ntcreatex
.in
.ea_list
= NULL
;
2240 io
->ntcreatex
.in
.sec_desc
= NULL
;
2241 io
->ntcreatex
.in
.query_maximal_access
= false;
2242 io
->ntcreatex
.in
.private_flags
= 0;
2244 /* we need a neater way to handle this alignment */
2245 if ((req
->flags2
& FLAGS2_UNICODE_STRINGS
) &&
2246 ucs2_align(req
->in
.buffer
, req
->in
.data
, STR_TERMINATE
|STR_UNICODE
)) {
2250 req_pull_string(&req
->in
.bufinfo
, &io
->ntcreatex
.in
.fname
, req
->in
.data
, fname_len
, STR_TERMINATE
);
2251 if (!io
->ntcreatex
.in
.fname
) {
2252 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2256 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, io
));
2260 /****************************************************************************
2261 Reply to an SMBntcancel request
2262 ****************************************************************************/
2263 void smbsrv_reply_ntcancel(struct smbsrv_request
*req
)
2265 struct smbsrv_request
*r
;
2266 uint16_t tid
= SVAL(req
->in
.hdr
,HDR_TID
);
2267 uint16_t uid
= SVAL(req
->in
.hdr
,HDR_UID
);
2268 uint16_t mid
= SVAL(req
->in
.hdr
,HDR_MID
);
2269 uint16_t pid
= SVAL(req
->in
.hdr
,HDR_PID
);
2271 for (r
= req
->smb_conn
->requests
; r
; r
= r
->next
) {
2272 if (tid
!= SVAL(r
->in
.hdr
,HDR_TID
)) continue;
2273 if (uid
!= SVAL(r
->in
.hdr
,HDR_UID
)) continue;
2274 if (mid
!= SVAL(r
->in
.hdr
,HDR_MID
)) continue;
2275 if (pid
!= SVAL(r
->in
.hdr
,HDR_PID
)) continue;
2277 SMBSRV_CHECK(ntvfs_cancel(r
->ntvfs
));
2279 /* NOTE: this request does not generate a reply */
2284 /* TODO: workout the correct error code,
2285 * until we know how the smb signing works
2286 * for ntcancel replies, don't send an error
2288 /*smbsrv_send_error(req, NT_STATUS_FOOBAR);*/
2293 parse the called/calling names from session request
2295 static NTSTATUS
parse_session_request(struct smbsrv_request
*req
)
2300 blob
.data
= req
->in
.buffer
+ 4;
2301 blob
.length
= ascii_len_n((const char *)blob
.data
, req
->in
.size
- PTR_DIFF(blob
.data
, req
->in
.buffer
));
2302 if (blob
.length
== 0) return NT_STATUS_BAD_NETWORK_NAME
;
2304 req
->smb_conn
->negotiate
.called_name
= talloc(req
->smb_conn
, struct nbt_name
);
2305 req
->smb_conn
->negotiate
.calling_name
= talloc(req
->smb_conn
, struct nbt_name
);
2306 if (req
->smb_conn
->negotiate
.called_name
== NULL
||
2307 req
->smb_conn
->negotiate
.calling_name
== NULL
) {
2308 return NT_STATUS_NO_MEMORY
;
2311 status
= nbt_name_from_blob(req
->smb_conn
, &blob
,
2312 req
->smb_conn
->negotiate
.called_name
);
2313 NT_STATUS_NOT_OK_RETURN(status
);
2315 blob
.data
+= blob
.length
;
2316 blob
.length
= ascii_len_n((const char *)blob
.data
, req
->in
.size
- PTR_DIFF(blob
.data
, req
->in
.buffer
));
2317 if (blob
.length
== 0) return NT_STATUS_BAD_NETWORK_NAME
;
2319 status
= nbt_name_from_blob(req
->smb_conn
, &blob
,
2320 req
->smb_conn
->negotiate
.calling_name
);
2321 NT_STATUS_NOT_OK_RETURN(status
);
2323 req
->smb_conn
->negotiate
.done_nbt_session
= true;
2325 return NT_STATUS_OK
;
2330 /****************************************************************************
2331 Reply to a special message - a SMB packet with non zero NBT message type
2332 ****************************************************************************/
2333 void smbsrv_reply_special(struct smbsrv_request
*req
)
2336 uint8_t *buf
= talloc_zero_array(req
, uint8_t, 4);
2338 msg_type
= CVAL(req
->in
.buffer
,0);
2343 case NBSSrequest
: /* session request */
2344 if (req
->smb_conn
->negotiate
.done_nbt_session
) {
2345 DEBUG(0,("Warning: ignoring secondary session request\n"));
2352 /* we don't check the status - samba always accepts session
2353 requests for any name */
2354 parse_session_request(req
);
2356 req
->out
.buffer
= buf
;
2358 smbsrv_send_reply_nosign(req
);
2361 case 0x89: /* session keepalive request
2362 (some old clients produce this?) */
2363 SCVAL(buf
, 0, NBSSkeepalive
);
2365 req
->out
.buffer
= buf
;
2367 smbsrv_send_reply_nosign(req
);
2371 /* session keepalive - swallow it */
2376 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type
));