2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-2005
5 Copyright (C) James J Myers 2003 <myersjj@samba.org>
6 Copyright (C) Stefan Metzmacher 2004-2005
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "system/time.h"
25 #include "smbd/service_stream.h"
26 #include "smb_server/smb_server.h"
27 #include "ntvfs/ntvfs.h"
31 send an oplock break request to a client
33 BOOL req_send_oplock_break(struct smbsrv_tcon *tcon, uint16_t fnum, uint8_t level)
35 struct smbsrv_request *req;
37 req = init_smb_request(tcon->smb_conn);
39 req_setup_reply(req, 8, 0);
41 SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
42 SSVAL(req->out.hdr,HDR_TID,tcon->tid);
43 SSVAL(req->out.hdr,HDR_PID,0xFFFF);
44 SSVAL(req->out.hdr,HDR_UID,0);
45 SSVAL(req->out.hdr,HDR_MID,0xFFFF);
46 SCVAL(req->out.hdr,HDR_FLG,0);
47 SSVAL(req->out.hdr,HDR_FLG2,0);
49 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
50 SSVAL(req->out.vwv, VWV(1), 0);
51 SSVAL(req->out.vwv, VWV(2), fnum);
52 SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
53 SCVAL(req->out.vwv, VWV(3)+1, level);
54 SIVAL(req->out.vwv, VWV(4), 0);
55 SSVAL(req->out.vwv, VWV(6), 0);
56 SSVAL(req->out.vwv, VWV(7), 0);
62 static void switch_message(int type, struct smbsrv_request *req);
64 /****************************************************************************
65 receive a SMB request header from the wire, forming a request_context
67 ****************************************************************************/
68 NTSTATUS smbsrv_recv_smb_request(void *private, DATA_BLOB blob)
70 struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection);
71 struct smbsrv_request *req;
74 /* see if its a special NBT packet */
75 if (CVAL(blob.data, 0) != 0) {
76 req = init_smb_request(smb_conn);
77 NT_STATUS_HAVE_NO_MEMORY(req);
81 req->in.buffer = talloc_steal(req, blob.data);
82 req->in.size = blob.length;
83 req->request_time = timeval_current();
89 if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) {
90 DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length));
91 smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
95 /* Make sure this is an SMB packet */
96 if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) {
97 DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n",
99 smbsrv_terminate_connection(smb_conn, "Non-SMB packet");
103 req = init_smb_request(smb_conn);
104 NT_STATUS_HAVE_NO_MEMORY(req);
106 req->in.buffer = talloc_steal(req, blob.data);
107 req->in.size = blob.length;
108 req->request_time = timeval_current();
109 req->chained_fnum = -1;
110 req->in.allocated = req->in.size;
111 req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
112 req->in.vwv = req->in.hdr + HDR_VWV;
113 req->in.wct = CVAL(req->in.hdr, HDR_WCT);
114 if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) {
115 req->in.data = req->in.vwv + VWV(req->in.wct) + 2;
116 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
118 /* the bcc length is only 16 bits, but some packets
119 (such as SMBwriteX) can be much larger than 64k. We
120 detect this by looking for a large non-chained NBT
121 packet (at least 64k bigger than what is
122 specified). If it is detected then the NBT size is
123 used instead of the bcc size */
124 if (req->in.data_size + 0x10000 <=
125 req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
126 (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE)) {
127 /* its an oversized packet! fun for all the family */
128 req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
132 if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) {
133 DEBUG(2,("Invalid SMB word count %d\n", req->in.wct));
134 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
138 if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) {
139 DEBUG(2,("Invalid SMB buffer length count %d\n", req->in.data_size));
140 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
144 req->flags = CVAL(req->in.hdr, HDR_FLG);
145 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
146 req->smbpid = SVAL(req->in.hdr, HDR_PID);
148 if (!req_signing_check_incoming(req)) {
149 req_reply_error(req, NT_STATUS_ACCESS_DENIED);
153 command = CVAL(req->in.hdr, HDR_COM);
154 switch_message(command, req);
159 These flags determine some of the permissions required to do an operation
161 #define AS_USER (1<<0)
162 #define SIGNING_NO_REPLY (1<<1)
165 define a list of possible SMB messages and their corresponding
166 functions. Any message that has a NULL function is unimplemented -
167 please feel free to contribute implementations!
169 static const struct smb_message_struct
172 void (*fn)(struct smbsrv_request *);
175 smb_messages[256] = {
176 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER},
177 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER},
178 /* 0x02 */ { "SMBopen",reply_open,AS_USER},
179 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
180 /* 0x04 */ { "SMBclose",reply_close,AS_USER},
181 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
182 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER},
183 /* 0x07 */ { "SMBmv",reply_mv,AS_USER},
184 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
185 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER},
186 /* 0x0a */ { "SMBread",reply_read,AS_USER},
187 /* 0x0b */ { "SMBwrite",reply_write,AS_USER},
188 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
189 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
190 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
191 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
192 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
193 /* 0x11 */ { "SMBexit",reply_exit,0},
194 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
195 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
196 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
197 /* 0x15 */ { NULL, NULL, 0 },
198 /* 0x16 */ { NULL, NULL, 0 },
199 /* 0x17 */ { NULL, NULL, 0 },
200 /* 0x18 */ { NULL, NULL, 0 },
201 /* 0x19 */ { NULL, NULL, 0 },
202 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
203 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
204 /* 0x1c */ { "SMBreadBs",NULL,0 },
205 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
206 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
207 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
208 /* 0x20 */ { "SMBwritec",NULL,0},
209 /* 0x21 */ { NULL, NULL, 0 },
210 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER},
211 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER},
212 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER},
213 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER},
214 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER},
215 /* 0x27 */ { "SMBioctl",reply_ioctl,AS_USER},
216 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
217 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER},
218 /* 0x2a */ { "SMBmove",NULL,AS_USER},
219 /* 0x2b */ { "SMBecho",reply_echo,0},
220 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
221 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER},
222 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER},
223 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER},
224 /* 0x30 */ { NULL, NULL, 0 },
225 /* 0x31 */ { NULL, NULL, 0 },
226 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER},
227 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
228 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
229 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
230 /* 0x36 */ { NULL, NULL, 0 },
231 /* 0x37 */ { NULL, NULL, 0 },
232 /* 0x38 */ { NULL, NULL, 0 },
233 /* 0x39 */ { NULL, NULL, 0 },
234 /* 0x3a */ { NULL, NULL, 0 },
235 /* 0x3b */ { NULL, NULL, 0 },
236 /* 0x3c */ { NULL, NULL, 0 },
237 /* 0x3d */ { NULL, NULL, 0 },
238 /* 0x3e */ { NULL, NULL, 0 },
239 /* 0x3f */ { NULL, NULL, 0 },
240 /* 0x40 */ { NULL, NULL, 0 },
241 /* 0x41 */ { NULL, NULL, 0 },
242 /* 0x42 */ { NULL, NULL, 0 },
243 /* 0x43 */ { NULL, NULL, 0 },
244 /* 0x44 */ { NULL, NULL, 0 },
245 /* 0x45 */ { NULL, NULL, 0 },
246 /* 0x46 */ { NULL, NULL, 0 },
247 /* 0x47 */ { NULL, NULL, 0 },
248 /* 0x48 */ { NULL, NULL, 0 },
249 /* 0x49 */ { NULL, NULL, 0 },
250 /* 0x4a */ { NULL, NULL, 0 },
251 /* 0x4b */ { NULL, NULL, 0 },
252 /* 0x4c */ { NULL, NULL, 0 },
253 /* 0x4d */ { NULL, NULL, 0 },
254 /* 0x4e */ { NULL, NULL, 0 },
255 /* 0x4f */ { NULL, NULL, 0 },
256 /* 0x50 */ { NULL, NULL, 0 },
257 /* 0x51 */ { NULL, NULL, 0 },
258 /* 0x52 */ { NULL, NULL, 0 },
259 /* 0x53 */ { NULL, NULL, 0 },
260 /* 0x54 */ { NULL, NULL, 0 },
261 /* 0x55 */ { NULL, NULL, 0 },
262 /* 0x56 */ { NULL, NULL, 0 },
263 /* 0x57 */ { NULL, NULL, 0 },
264 /* 0x58 */ { NULL, NULL, 0 },
265 /* 0x59 */ { NULL, NULL, 0 },
266 /* 0x5a */ { NULL, NULL, 0 },
267 /* 0x5b */ { NULL, NULL, 0 },
268 /* 0x5c */ { NULL, NULL, 0 },
269 /* 0x5d */ { NULL, NULL, 0 },
270 /* 0x5e */ { NULL, NULL, 0 },
271 /* 0x5f */ { NULL, NULL, 0 },
272 /* 0x60 */ { NULL, NULL, 0 },
273 /* 0x61 */ { NULL, NULL, 0 },
274 /* 0x62 */ { NULL, NULL, 0 },
275 /* 0x63 */ { NULL, NULL, 0 },
276 /* 0x64 */ { NULL, NULL, 0 },
277 /* 0x65 */ { NULL, NULL, 0 },
278 /* 0x66 */ { NULL, NULL, 0 },
279 /* 0x67 */ { NULL, NULL, 0 },
280 /* 0x68 */ { NULL, NULL, 0 },
281 /* 0x69 */ { NULL, NULL, 0 },
282 /* 0x6a */ { NULL, NULL, 0 },
283 /* 0x6b */ { NULL, NULL, 0 },
284 /* 0x6c */ { NULL, NULL, 0 },
285 /* 0x6d */ { NULL, NULL, 0 },
286 /* 0x6e */ { NULL, NULL, 0 },
287 /* 0x6f */ { NULL, NULL, 0 },
288 /* 0x70 */ { "SMBtcon",reply_tcon,0},
289 /* 0x71 */ { "SMBtdis",reply_tdis,0},
290 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
291 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup,0},
292 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
293 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
294 /* 0x76 */ { NULL, NULL, 0 },
295 /* 0x77 */ { NULL, NULL, 0 },
296 /* 0x78 */ { NULL, NULL, 0 },
297 /* 0x79 */ { NULL, NULL, 0 },
298 /* 0x7a */ { NULL, NULL, 0 },
299 /* 0x7b */ { NULL, NULL, 0 },
300 /* 0x7c */ { NULL, NULL, 0 },
301 /* 0x7d */ { NULL, NULL, 0 },
302 /* 0x7e */ { NULL, NULL, 0 },
303 /* 0x7f */ { NULL, NULL, 0 },
304 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
305 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
306 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
307 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
308 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
309 /* 0x85 */ { NULL, NULL, 0 },
310 /* 0x86 */ { NULL, NULL, 0 },
311 /* 0x87 */ { NULL, NULL, 0 },
312 /* 0x88 */ { NULL, NULL, 0 },
313 /* 0x89 */ { NULL, NULL, 0 },
314 /* 0x8a */ { NULL, NULL, 0 },
315 /* 0x8b */ { NULL, NULL, 0 },
316 /* 0x8c */ { NULL, NULL, 0 },
317 /* 0x8d */ { NULL, NULL, 0 },
318 /* 0x8e */ { NULL, NULL, 0 },
319 /* 0x8f */ { NULL, NULL, 0 },
320 /* 0x90 */ { NULL, NULL, 0 },
321 /* 0x91 */ { NULL, NULL, 0 },
322 /* 0x92 */ { NULL, NULL, 0 },
323 /* 0x93 */ { NULL, NULL, 0 },
324 /* 0x94 */ { NULL, NULL, 0 },
325 /* 0x95 */ { NULL, NULL, 0 },
326 /* 0x96 */ { NULL, NULL, 0 },
327 /* 0x97 */ { NULL, NULL, 0 },
328 /* 0x98 */ { NULL, NULL, 0 },
329 /* 0x99 */ { NULL, NULL, 0 },
330 /* 0x9a */ { NULL, NULL, 0 },
331 /* 0x9b */ { NULL, NULL, 0 },
332 /* 0x9c */ { NULL, NULL, 0 },
333 /* 0x9d */ { NULL, NULL, 0 },
334 /* 0x9e */ { NULL, NULL, 0 },
335 /* 0x9f */ { NULL, NULL, 0 },
336 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER},
337 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER},
338 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER},
339 /* 0xa3 */ { NULL, NULL, 0 },
340 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, AS_USER|SIGNING_NO_REPLY},
341 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER},
342 /* 0xa6 */ { NULL, NULL, 0 },
343 /* 0xa7 */ { NULL, NULL, 0 },
344 /* 0xa8 */ { NULL, NULL, 0 },
345 /* 0xa9 */ { NULL, NULL, 0 },
346 /* 0xaa */ { NULL, NULL, 0 },
347 /* 0xab */ { NULL, NULL, 0 },
348 /* 0xac */ { NULL, NULL, 0 },
349 /* 0xad */ { NULL, NULL, 0 },
350 /* 0xae */ { NULL, NULL, 0 },
351 /* 0xaf */ { NULL, NULL, 0 },
352 /* 0xb0 */ { NULL, NULL, 0 },
353 /* 0xb1 */ { NULL, NULL, 0 },
354 /* 0xb2 */ { NULL, NULL, 0 },
355 /* 0xb3 */ { NULL, NULL, 0 },
356 /* 0xb4 */ { NULL, NULL, 0 },
357 /* 0xb5 */ { NULL, NULL, 0 },
358 /* 0xb6 */ { NULL, NULL, 0 },
359 /* 0xb7 */ { NULL, NULL, 0 },
360 /* 0xb8 */ { NULL, NULL, 0 },
361 /* 0xb9 */ { NULL, NULL, 0 },
362 /* 0xba */ { NULL, NULL, 0 },
363 /* 0xbb */ { NULL, NULL, 0 },
364 /* 0xbc */ { NULL, NULL, 0 },
365 /* 0xbd */ { NULL, NULL, 0 },
366 /* 0xbe */ { NULL, NULL, 0 },
367 /* 0xbf */ { NULL, NULL, 0 },
368 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER },
369 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
370 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
371 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
372 /* 0xc4 */ { NULL, NULL, 0 },
373 /* 0xc5 */ { NULL, NULL, 0 },
374 /* 0xc6 */ { NULL, NULL, 0 },
375 /* 0xc7 */ { NULL, NULL, 0 },
376 /* 0xc8 */ { NULL, NULL, 0 },
377 /* 0xc9 */ { NULL, NULL, 0 },
378 /* 0xca */ { NULL, NULL, 0 },
379 /* 0xcb */ { NULL, NULL, 0 },
380 /* 0xcc */ { NULL, NULL, 0 },
381 /* 0xcd */ { NULL, NULL, 0 },
382 /* 0xce */ { NULL, NULL, 0 },
383 /* 0xcf */ { NULL, NULL, 0 },
384 /* 0xd0 */ { "SMBsends",reply_sends,0},
385 /* 0xd1 */ { "SMBsendb",NULL,0},
386 /* 0xd2 */ { "SMBfwdname",NULL,0},
387 /* 0xd3 */ { "SMBcancelf",NULL,0},
388 /* 0xd4 */ { "SMBgetmac",NULL,0},
389 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,0},
390 /* 0xd6 */ { "SMBsendend",reply_sendend,0},
391 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,0},
392 /* 0xd8 */ { NULL, NULL, 0 },
393 /* 0xd9 */ { NULL, NULL, 0 },
394 /* 0xda */ { NULL, NULL, 0 },
395 /* 0xdb */ { NULL, NULL, 0 },
396 /* 0xdc */ { NULL, NULL, 0 },
397 /* 0xdd */ { NULL, NULL, 0 },
398 /* 0xde */ { NULL, NULL, 0 },
399 /* 0xdf */ { NULL, NULL, 0 },
400 /* 0xe0 */ { NULL, NULL, 0 },
401 /* 0xe1 */ { NULL, NULL, 0 },
402 /* 0xe2 */ { NULL, NULL, 0 },
403 /* 0xe3 */ { NULL, NULL, 0 },
404 /* 0xe4 */ { NULL, NULL, 0 },
405 /* 0xe5 */ { NULL, NULL, 0 },
406 /* 0xe6 */ { NULL, NULL, 0 },
407 /* 0xe7 */ { NULL, NULL, 0 },
408 /* 0xe8 */ { NULL, NULL, 0 },
409 /* 0xe9 */ { NULL, NULL, 0 },
410 /* 0xea */ { NULL, NULL, 0 },
411 /* 0xeb */ { NULL, NULL, 0 },
412 /* 0xec */ { NULL, NULL, 0 },
413 /* 0xed */ { NULL, NULL, 0 },
414 /* 0xee */ { NULL, NULL, 0 },
415 /* 0xef */ { NULL, NULL, 0 },
416 /* 0xf0 */ { NULL, NULL, 0 },
417 /* 0xf1 */ { NULL, NULL, 0 },
418 /* 0xf2 */ { NULL, NULL, 0 },
419 /* 0xf3 */ { NULL, NULL, 0 },
420 /* 0xf4 */ { NULL, NULL, 0 },
421 /* 0xf5 */ { NULL, NULL, 0 },
422 /* 0xf6 */ { NULL, NULL, 0 },
423 /* 0xf7 */ { NULL, NULL, 0 },
424 /* 0xf8 */ { NULL, NULL, 0 },
425 /* 0xf9 */ { NULL, NULL, 0 },
426 /* 0xfa */ { NULL, NULL, 0 },
427 /* 0xfb */ { NULL, NULL, 0 },
428 /* 0xfc */ { NULL, NULL, 0 },
429 /* 0xfd */ { NULL, NULL, 0 },
430 /* 0xfe */ { NULL, NULL, 0 },
431 /* 0xff */ { NULL, NULL, 0 }
434 /****************************************************************************
435 return a string containing the function name of a SMB command
436 ****************************************************************************/
437 static const char *smb_fn_name(uint8_t type)
439 const char *unknown_name = "SMBunknown";
441 if (smb_messages[type].name == NULL)
444 return smb_messages[type].name;
448 /****************************************************************************
449 Do a switch on the message type and call the specific reply function for this
450 message. Unlike earlier versions of Samba the reply functions are responsible
451 for sending the reply themselves, rather than returning a size to this function
452 The reply functions may also choose to delay the processing by pushing the message
453 onto the message queue
454 ****************************************************************************/
455 static void switch_message(int type, struct smbsrv_request *req)
458 struct smbsrv_connection *smb_conn = req->smb_conn;
465 if (smb_messages[type].fn == NULL) {
466 DEBUG(0,("Unknown message type %d!\n",type));
471 flags = smb_messages[type].flags;
473 req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
476 /* setup the user context for this request if it
477 hasn't already been initialised (to cope with SMB
480 /* In share mode security we must ignore the vuid. */
481 if (smb_conn->config.security == SEC_SHARE) {
483 req->session = req->tcon->sec_share.session;
486 req->session = smbsrv_session_find(req->smb_conn, SVAL(req->in.hdr,HDR_UID));
490 DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->server_id));
492 /* this must be called before we do any reply */
493 if (flags & SIGNING_NO_REPLY) {
494 req_signing_no_reply(req);
497 /* see if the vuid is valid */
498 if ((flags & AS_USER) && !req->session) {
499 /* amazingly, the error code depends on the command */
503 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
506 status = NT_STATUS_INVALID_HANDLE;
511 * don't know how to handle smb signing for this case
512 * so just skip the reply
514 if ((flags & SIGNING_NO_REPLY) &&
515 (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
516 DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
517 smb_fn_name(type), nt_errstr(status)));
521 req_reply_error(req, status);
525 /* does this protocol need a valid tree connection? */
526 if ((flags & AS_USER) && !req->tcon) {
527 /* amazingly, the error code depends on the command */
531 status = NT_STATUS_DOS(ERRSRV, ERRinvnid);
534 status = NT_STATUS_INVALID_HANDLE;
539 * don't know how to handle smb signing for this case
540 * so just skip the reply
542 if ((flags & SIGNING_NO_REPLY) &&
543 (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
544 DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
545 smb_fn_name(type), nt_errstr(status)));
549 req_reply_error(req, status);
553 smb_messages[type].fn(req);
557 we call this when first first part of a possibly chained request has been completed
558 and we need to call the 2nd part, if any
560 void chain_reply(struct smbsrv_request *req)
562 uint16_t chain_cmd, chain_offset;
567 if (req->in.wct < 2 || req->out.wct < 2) {
568 req_reply_dos_error(req, ERRSRV, ERRerror);
572 chain_cmd = CVAL(req->in.vwv, VWV(0));
573 chain_offset = SVAL(req->in.vwv, VWV(1));
575 if (chain_cmd == SMB_CHAIN_NONE) {
577 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
578 SSVAL(req->out.vwv, VWV(1), 0);
583 if (chain_offset + req->in.hdr >= req->in.buffer + req->in.size) {
587 wct = CVAL(req->in.hdr, chain_offset);
588 vwv = req->in.hdr + chain_offset + 1;
590 if (vwv + VWV(wct) + 2 > req->in.buffer + req->in.size) {
594 data_size = SVAL(vwv, VWV(wct));
595 data = vwv + VWV(wct) + 2;
597 if (data + data_size > req->in.buffer + req->in.size) {
601 /* all seems legit */
605 req->in.data_size = data_size;
610 SSVAL(req->out.vwv, VWV(0), chain_cmd);
611 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
613 /* the current request in the chain might have used an async reply,
614 but that doesn't mean the next element needs to */
615 ZERO_STRUCTP(req->async_states);
617 switch_message(chain_cmd, req);
621 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
622 SSVAL(req->out.vwv, VWV(1), 0);
623 req_reply_dos_error(req, ERRSRV, ERRerror);
627 * init the SMB protocol related stuff
629 NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn)
633 /* now initialise a few default values associated with this smb socket */
634 smb_conn->negotiate.max_send = 0xFFFF;
636 /* this is the size that w2k uses, and it appears to be important for
638 smb_conn->negotiate.max_recv = lp_max_xmit();
640 smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
642 smb_conn->config.security = lp_security();
643 smb_conn->config.nt_status_support = lp_nt_status_support();
645 status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
646 NT_STATUS_NOT_OK_RETURN(status);
648 status = smbsrv_smb_init_tcons(smb_conn);
649 NT_STATUS_NOT_OK_RETURN(status);
651 srv_init_signing(smb_conn);