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 NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level)
35 struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon);
36 struct smbsrv_request *req;
38 req = smbsrv_init_request(tcon->smb_conn);
39 NT_STATUS_HAVE_NO_MEMORY(req);
41 smbsrv_setup_reply(req, 8, 0);
43 SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
44 SSVAL(req->out.hdr,HDR_TID,tcon->tid);
45 SSVAL(req->out.hdr,HDR_PID,0xFFFF);
46 SSVAL(req->out.hdr,HDR_UID,0);
47 SSVAL(req->out.hdr,HDR_MID,0xFFFF);
48 SCVAL(req->out.hdr,HDR_FLG,0);
49 SSVAL(req->out.hdr,HDR_FLG2,0);
51 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
52 SSVAL(req->out.vwv, VWV(1), 0);
53 SSVAL(req->out.vwv, VWV(2), fnum);
54 SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
55 SCVAL(req->out.vwv, VWV(3)+1, level);
56 SIVAL(req->out.vwv, VWV(4), 0);
57 SSVAL(req->out.vwv, VWV(6), 0);
58 SSVAL(req->out.vwv, VWV(7), 0);
60 smbsrv_send_reply(req);
64 static void switch_message(int type, struct smbsrv_request *req);
66 /****************************************************************************
67 receive a SMB request header from the wire, forming a request_context
69 ****************************************************************************/
70 NTSTATUS smbsrv_recv_smb_request(void *private, DATA_BLOB blob)
72 struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection);
73 struct smbsrv_request *req;
76 /* see if its a special NBT packet */
77 if (CVAL(blob.data, 0) != 0) {
78 req = smbsrv_init_request(smb_conn);
79 NT_STATUS_HAVE_NO_MEMORY(req);
83 req->in.buffer = talloc_steal(req, blob.data);
84 req->in.size = blob.length;
85 req->request_time = timeval_current();
87 smbsrv_reply_special(req);
91 if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) {
92 DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length));
93 smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
97 /* Make sure this is an SMB packet */
98 if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) {
99 DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n",
101 smbsrv_terminate_connection(smb_conn, "Non-SMB packet");
105 req = smbsrv_init_request(smb_conn);
106 NT_STATUS_HAVE_NO_MEMORY(req);
108 req->in.buffer = talloc_steal(req, blob.data);
109 req->in.size = blob.length;
110 req->request_time = timeval_current();
111 req->chained_fnum = -1;
112 req->in.allocated = req->in.size;
113 req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
114 req->in.vwv = req->in.hdr + HDR_VWV;
115 req->in.wct = CVAL(req->in.hdr, HDR_WCT);
116 if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) {
117 req->in.data = req->in.vwv + VWV(req->in.wct) + 2;
118 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
120 /* the bcc length is only 16 bits, but some packets
121 (such as SMBwriteX) can be much larger than 64k. We
122 detect this by looking for a large non-chained NBT
123 packet (at least 64k bigger than what is
124 specified). If it is detected then the NBT size is
125 used instead of the bcc size */
126 if (req->in.data_size + 0x10000 <=
127 req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
128 (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE)) {
129 /* its an oversized packet! fun for all the family */
130 req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
134 if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) {
135 DEBUG(2,("Invalid SMB word count %d\n", req->in.wct));
136 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
140 if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) {
141 DEBUG(2,("Invalid SMB buffer length count %d\n", req->in.data_size));
142 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
146 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
148 if (!smbsrv_signing_check_incoming(req)) {
149 smbsrv_send_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 NEED_SESS (1<<0)
162 #define NEED_TCON (1<<1)
163 #define SIGNING_NO_REPLY (1<<2)
166 define a list of possible SMB messages and their corresponding
167 functions. Any message that has a NULL function is unimplemented -
168 please feel free to contribute implementations!
170 static const struct smb_message_struct
173 void (*fn)(struct smbsrv_request *);
176 smb_messages[256] = {
177 /* 0x00 */ { "SMBmkdir", smbsrv_reply_mkdir, NEED_SESS|NEED_TCON },
178 /* 0x01 */ { "SMBrmdir", smbsrv_reply_rmdir, NEED_SESS|NEED_TCON },
179 /* 0x02 */ { "SMBopen", smbsrv_reply_open, NEED_SESS|NEED_TCON },
180 /* 0x03 */ { "SMBcreate", smbsrv_reply_mknew, NEED_SESS|NEED_TCON },
181 /* 0x04 */ { "SMBclose", smbsrv_reply_close, NEED_SESS|NEED_TCON },
182 /* 0x05 */ { "SMBflush", smbsrv_reply_flush, NEED_SESS|NEED_TCON },
183 /* 0x06 */ { "SMBunlink", smbsrv_reply_unlink, NEED_SESS|NEED_TCON },
184 /* 0x07 */ { "SMBmv", smbsrv_reply_mv, NEED_SESS|NEED_TCON },
185 /* 0x08 */ { "SMBgetatr", smbsrv_reply_getatr, NEED_SESS|NEED_TCON },
186 /* 0x09 */ { "SMBsetatr", smbsrv_reply_setatr, NEED_SESS|NEED_TCON },
187 /* 0x0a */ { "SMBread", smbsrv_reply_read, NEED_SESS|NEED_TCON },
188 /* 0x0b */ { "SMBwrite", smbsrv_reply_write, NEED_SESS|NEED_TCON },
189 /* 0x0c */ { "SMBlock", smbsrv_reply_lock, NEED_SESS|NEED_TCON },
190 /* 0x0d */ { "SMBunlock", smbsrv_reply_unlock, NEED_SESS|NEED_TCON },
191 /* 0x0e */ { "SMBctemp", smbsrv_reply_ctemp, NEED_SESS|NEED_TCON },
192 /* 0x0f */ { "SMBmknew", smbsrv_reply_mknew, NEED_SESS|NEED_TCON },
193 /* 0x10 */ { "SMBchkpth", smbsrv_reply_chkpth, NEED_SESS|NEED_TCON },
194 /* 0x11 */ { "SMBexit", smbsrv_reply_exit, NEED_SESS },
195 /* 0x12 */ { "SMBlseek", smbsrv_reply_lseek, NEED_SESS|NEED_TCON },
196 /* 0x13 */ { "SMBlockread", smbsrv_reply_lockread, NEED_SESS|NEED_TCON },
197 /* 0x14 */ { "SMBwriteunlock", smbsrv_reply_writeunlock, NEED_SESS|NEED_TCON },
198 /* 0x15 */ { NULL, NULL, 0 },
199 /* 0x16 */ { NULL, NULL, 0 },
200 /* 0x17 */ { NULL, NULL, 0 },
201 /* 0x18 */ { NULL, NULL, 0 },
202 /* 0x19 */ { NULL, NULL, 0 },
203 /* 0x1a */ { "SMBreadbraw", smbsrv_reply_readbraw, NEED_SESS|NEED_TCON },
204 /* 0x1b */ { "SMBreadBmpx", smbsrv_reply_readbmpx, NEED_SESS|NEED_TCON },
205 /* 0x1c */ { "SMBreadBs", NULL, 0 },
206 /* 0x1d */ { "SMBwritebraw", smbsrv_reply_writebraw, NEED_SESS|NEED_TCON },
207 /* 0x1e */ { "SMBwriteBmpx", smbsrv_reply_writebmpx, NEED_SESS|NEED_TCON },
208 /* 0x1f */ { "SMBwriteBs", smbsrv_reply_writebs, NEED_SESS|NEED_TCON },
209 /* 0x20 */ { "SMBwritec", NULL, 0 },
210 /* 0x21 */ { NULL, NULL, 0 },
211 /* 0x22 */ { "SMBsetattrE", smbsrv_reply_setattrE, NEED_SESS|NEED_TCON },
212 /* 0x23 */ { "SMBgetattrE", smbsrv_reply_getattrE, NEED_SESS|NEED_TCON },
213 /* 0x24 */ { "SMBlockingX", smbsrv_reply_lockingX, NEED_SESS|NEED_TCON },
214 /* 0x25 */ { "SMBtrans", smbsrv_reply_trans, NEED_SESS|NEED_TCON },
215 /* 0x26 */ { "SMBtranss", smbsrv_reply_transs, NEED_SESS|NEED_TCON },
216 /* 0x27 */ { "SMBioctl", smbsrv_reply_ioctl, NEED_SESS|NEED_TCON },
217 /* 0x28 */ { "SMBioctls", NULL, NEED_SESS|NEED_TCON },
218 /* 0x29 */ { "SMBcopy", smbsrv_reply_copy, NEED_SESS|NEED_TCON },
219 /* 0x2a */ { "SMBmove", NULL, NEED_SESS|NEED_TCON },
220 /* 0x2b */ { "SMBecho", smbsrv_reply_echo, 0 },
221 /* 0x2c */ { "SMBwriteclose", smbsrv_reply_writeclose, NEED_SESS|NEED_TCON },
222 /* 0x2d */ { "SMBopenX", smbsrv_reply_open_and_X, NEED_SESS|NEED_TCON },
223 /* 0x2e */ { "SMBreadX", smbsrv_reply_read_and_X, NEED_SESS|NEED_TCON },
224 /* 0x2f */ { "SMBwriteX", smbsrv_reply_write_and_X, NEED_SESS|NEED_TCON},
225 /* 0x30 */ { NULL, NULL, 0 },
226 /* 0x31 */ { NULL, NULL, 0 },
227 /* 0x32 */ { "SMBtrans2", smbsrv_reply_trans2, NEED_SESS|NEED_TCON },
228 /* 0x33 */ { "SMBtranss2", smbsrv_reply_transs2, NEED_SESS|NEED_TCON },
229 /* 0x34 */ { "SMBfindclose", smbsrv_reply_findclose, NEED_SESS|NEED_TCON },
230 /* 0x35 */ { "SMBfindnclose", smbsrv_reply_findnclose, NEED_SESS|NEED_TCON },
231 /* 0x36 */ { NULL, NULL, 0 },
232 /* 0x37 */ { NULL, NULL, 0 },
233 /* 0x38 */ { NULL, NULL, 0 },
234 /* 0x39 */ { NULL, NULL, 0 },
235 /* 0x3a */ { NULL, NULL, 0 },
236 /* 0x3b */ { NULL, NULL, 0 },
237 /* 0x3c */ { NULL, NULL, 0 },
238 /* 0x3d */ { NULL, NULL, 0 },
239 /* 0x3e */ { NULL, NULL, 0 },
240 /* 0x3f */ { NULL, NULL, 0 },
241 /* 0x40 */ { NULL, NULL, 0 },
242 /* 0x41 */ { NULL, NULL, 0 },
243 /* 0x42 */ { NULL, NULL, 0 },
244 /* 0x43 */ { NULL, NULL, 0 },
245 /* 0x44 */ { NULL, NULL, 0 },
246 /* 0x45 */ { NULL, NULL, 0 },
247 /* 0x46 */ { NULL, NULL, 0 },
248 /* 0x47 */ { NULL, NULL, 0 },
249 /* 0x48 */ { NULL, NULL, 0 },
250 /* 0x49 */ { NULL, NULL, 0 },
251 /* 0x4a */ { NULL, NULL, 0 },
252 /* 0x4b */ { NULL, NULL, 0 },
253 /* 0x4c */ { NULL, NULL, 0 },
254 /* 0x4d */ { NULL, NULL, 0 },
255 /* 0x4e */ { NULL, NULL, 0 },
256 /* 0x4f */ { NULL, NULL, 0 },
257 /* 0x50 */ { NULL, NULL, 0 },
258 /* 0x51 */ { NULL, NULL, 0 },
259 /* 0x52 */ { NULL, NULL, 0 },
260 /* 0x53 */ { NULL, NULL, 0 },
261 /* 0x54 */ { NULL, NULL, 0 },
262 /* 0x55 */ { NULL, NULL, 0 },
263 /* 0x56 */ { NULL, NULL, 0 },
264 /* 0x57 */ { NULL, NULL, 0 },
265 /* 0x58 */ { NULL, NULL, 0 },
266 /* 0x59 */ { NULL, NULL, 0 },
267 /* 0x5a */ { NULL, NULL, 0 },
268 /* 0x5b */ { NULL, NULL, 0 },
269 /* 0x5c */ { NULL, NULL, 0 },
270 /* 0x5d */ { NULL, NULL, 0 },
271 /* 0x5e */ { NULL, NULL, 0 },
272 /* 0x5f */ { NULL, NULL, 0 },
273 /* 0x60 */ { NULL, NULL, 0 },
274 /* 0x61 */ { NULL, NULL, 0 },
275 /* 0x62 */ { NULL, NULL, 0 },
276 /* 0x63 */ { NULL, NULL, 0 },
277 /* 0x64 */ { NULL, NULL, 0 },
278 /* 0x65 */ { NULL, NULL, 0 },
279 /* 0x66 */ { NULL, NULL, 0 },
280 /* 0x67 */ { NULL, NULL, 0 },
281 /* 0x68 */ { NULL, NULL, 0 },
282 /* 0x69 */ { NULL, NULL, 0 },
283 /* 0x6a */ { NULL, NULL, 0 },
284 /* 0x6b */ { NULL, NULL, 0 },
285 /* 0x6c */ { NULL, NULL, 0 },
286 /* 0x6d */ { NULL, NULL, 0 },
287 /* 0x6e */ { NULL, NULL, 0 },
288 /* 0x6f */ { NULL, NULL, 0 },
289 /* 0x70 */ { "SMBtcon", smbsrv_reply_tcon, NEED_SESS },
290 /* 0x71 */ { "SMBtdis", smbsrv_reply_tdis, NEED_SESS },
291 /* 0x72 */ { "SMBnegprot", smbsrv_reply_negprot, 0 },
292 /* 0x73 */ { "SMBsesssetupX", smbsrv_reply_sesssetup, 0 },
293 /* 0x74 */ { "SMBulogoffX", smbsrv_reply_ulogoffX, NEED_SESS }, /* ulogoff doesn't give a valid TID */
294 /* 0x75 */ { "SMBtconX", smbsrv_reply_tcon_and_X, NEED_SESS },
295 /* 0x76 */ { NULL, NULL, 0 },
296 /* 0x77 */ { NULL, NULL, 0 },
297 /* 0x78 */ { NULL, NULL, 0 },
298 /* 0x79 */ { NULL, NULL, 0 },
299 /* 0x7a */ { NULL, NULL, 0 },
300 /* 0x7b */ { NULL, NULL, 0 },
301 /* 0x7c */ { NULL, NULL, 0 },
302 /* 0x7d */ { NULL, NULL, 0 },
303 /* 0x7e */ { NULL, NULL, 0 },
304 /* 0x7f */ { NULL, NULL, 0 },
305 /* 0x80 */ { "SMBdskattr", smbsrv_reply_dskattr, NEED_SESS|NEED_TCON },
306 /* 0x81 */ { "SMBsearch", smbsrv_reply_search, NEED_SESS|NEED_TCON },
307 /* 0x82 */ { "SMBffirst", smbsrv_reply_search, NEED_SESS|NEED_TCON },
308 /* 0x83 */ { "SMBfunique", smbsrv_reply_search, NEED_SESS|NEED_TCON },
309 /* 0x84 */ { "SMBfclose", smbsrv_reply_fclose, NEED_SESS|NEED_TCON },
310 /* 0x85 */ { NULL, NULL, 0 },
311 /* 0x86 */ { NULL, NULL, 0 },
312 /* 0x87 */ { NULL, NULL, 0 },
313 /* 0x88 */ { NULL, NULL, 0 },
314 /* 0x89 */ { NULL, NULL, 0 },
315 /* 0x8a */ { NULL, NULL, 0 },
316 /* 0x8b */ { NULL, NULL, 0 },
317 /* 0x8c */ { NULL, NULL, 0 },
318 /* 0x8d */ { NULL, NULL, 0 },
319 /* 0x8e */ { NULL, NULL, 0 },
320 /* 0x8f */ { NULL, NULL, 0 },
321 /* 0x90 */ { NULL, NULL, 0 },
322 /* 0x91 */ { NULL, NULL, 0 },
323 /* 0x92 */ { NULL, NULL, 0 },
324 /* 0x93 */ { NULL, NULL, 0 },
325 /* 0x94 */ { NULL, NULL, 0 },
326 /* 0x95 */ { NULL, NULL, 0 },
327 /* 0x96 */ { NULL, NULL, 0 },
328 /* 0x97 */ { NULL, NULL, 0 },
329 /* 0x98 */ { NULL, NULL, 0 },
330 /* 0x99 */ { NULL, NULL, 0 },
331 /* 0x9a */ { NULL, NULL, 0 },
332 /* 0x9b */ { NULL, NULL, 0 },
333 /* 0x9c */ { NULL, NULL, 0 },
334 /* 0x9d */ { NULL, NULL, 0 },
335 /* 0x9e */ { NULL, NULL, 0 },
336 /* 0x9f */ { NULL, NULL, 0 },
337 /* 0xa0 */ { "SMBnttrans", smbsrv_reply_nttrans, NEED_SESS|NEED_TCON },
338 /* 0xa1 */ { "SMBnttranss", smbsrv_reply_nttranss, NEED_SESS|NEED_TCON },
339 /* 0xa2 */ { "SMBntcreateX", smbsrv_reply_ntcreate_and_X, NEED_SESS|NEED_TCON },
340 /* 0xa3 */ { NULL, NULL, 0 },
341 /* 0xa4 */ { "SMBntcancel", smbsrv_reply_ntcancel, NEED_SESS|NEED_TCON|SIGNING_NO_REPLY },
342 /* 0xa5 */ { "SMBntrename", smbsrv_reply_ntrename, NEED_SESS|NEED_TCON },
343 /* 0xa6 */ { NULL, NULL, 0 },
344 /* 0xa7 */ { NULL, NULL, 0 },
345 /* 0xa8 */ { NULL, NULL, 0 },
346 /* 0xa9 */ { NULL, NULL, 0 },
347 /* 0xaa */ { NULL, NULL, 0 },
348 /* 0xab */ { NULL, NULL, 0 },
349 /* 0xac */ { NULL, NULL, 0 },
350 /* 0xad */ { NULL, NULL, 0 },
351 /* 0xae */ { NULL, NULL, 0 },
352 /* 0xaf */ { NULL, NULL, 0 },
353 /* 0xb0 */ { NULL, NULL, 0 },
354 /* 0xb1 */ { NULL, NULL, 0 },
355 /* 0xb2 */ { NULL, NULL, 0 },
356 /* 0xb3 */ { NULL, NULL, 0 },
357 /* 0xb4 */ { NULL, NULL, 0 },
358 /* 0xb5 */ { NULL, NULL, 0 },
359 /* 0xb6 */ { NULL, NULL, 0 },
360 /* 0xb7 */ { NULL, NULL, 0 },
361 /* 0xb8 */ { NULL, NULL, 0 },
362 /* 0xb9 */ { NULL, NULL, 0 },
363 /* 0xba */ { NULL, NULL, 0 },
364 /* 0xbb */ { NULL, NULL, 0 },
365 /* 0xbc */ { NULL, NULL, 0 },
366 /* 0xbd */ { NULL, NULL, 0 },
367 /* 0xbe */ { NULL, NULL, 0 },
368 /* 0xbf */ { NULL, NULL, 0 },
369 /* 0xc0 */ { "SMBsplopen", smbsrv_reply_printopen, NEED_SESS|NEED_TCON },
370 /* 0xc1 */ { "SMBsplwr", smbsrv_reply_printwrite, NEED_SESS|NEED_TCON },
371 /* 0xc2 */ { "SMBsplclose", smbsrv_reply_printclose, NEED_SESS|NEED_TCON },
372 /* 0xc3 */ { "SMBsplretq", smbsrv_reply_printqueue, NEED_SESS|NEED_TCON },
373 /* 0xc4 */ { NULL, NULL, 0 },
374 /* 0xc5 */ { NULL, NULL, 0 },
375 /* 0xc6 */ { NULL, NULL, 0 },
376 /* 0xc7 */ { NULL, NULL, 0 },
377 /* 0xc8 */ { NULL, NULL, 0 },
378 /* 0xc9 */ { NULL, NULL, 0 },
379 /* 0xca */ { NULL, NULL, 0 },
380 /* 0xcb */ { NULL, NULL, 0 },
381 /* 0xcc */ { NULL, NULL, 0 },
382 /* 0xcd */ { NULL, NULL, 0 },
383 /* 0xce */ { NULL, NULL, 0 },
384 /* 0xcf */ { NULL, NULL, 0 },
385 /* 0xd0 */ { "SMBsends", NULL, 0 },
386 /* 0xd1 */ { "SMBsendb", NULL, 0 },
387 /* 0xd2 */ { "SMBfwdname", NULL, 0 },
388 /* 0xd3 */ { "SMBcancelf", NULL, 0 },
389 /* 0xd4 */ { "SMBgetmac", NULL, 0 },
390 /* 0xd5 */ { "SMBsendstrt", NULL, 0 },
391 /* 0xd6 */ { "SMBsendend", NULL, 0 },
392 /* 0xd7 */ { "SMBsendtxt", NULL, 0 },
393 /* 0xd8 */ { NULL, NULL, 0 },
394 /* 0xd9 */ { NULL, NULL, 0 },
395 /* 0xda */ { NULL, NULL, 0 },
396 /* 0xdb */ { NULL, NULL, 0 },
397 /* 0xdc */ { NULL, NULL, 0 },
398 /* 0xdd */ { NULL, NULL, 0 },
399 /* 0xde */ { NULL, NULL, 0 },
400 /* 0xdf */ { NULL, NULL, 0 },
401 /* 0xe0 */ { NULL, NULL, 0 },
402 /* 0xe1 */ { NULL, NULL, 0 },
403 /* 0xe2 */ { NULL, NULL, 0 },
404 /* 0xe3 */ { NULL, NULL, 0 },
405 /* 0xe4 */ { NULL, NULL, 0 },
406 /* 0xe5 */ { NULL, NULL, 0 },
407 /* 0xe6 */ { NULL, NULL, 0 },
408 /* 0xe7 */ { NULL, NULL, 0 },
409 /* 0xe8 */ { NULL, NULL, 0 },
410 /* 0xe9 */ { NULL, NULL, 0 },
411 /* 0xea */ { NULL, NULL, 0 },
412 /* 0xeb */ { NULL, NULL, 0 },
413 /* 0xec */ { NULL, NULL, 0 },
414 /* 0xed */ { NULL, NULL, 0 },
415 /* 0xee */ { NULL, NULL, 0 },
416 /* 0xef */ { NULL, NULL, 0 },
417 /* 0xf0 */ { NULL, NULL, 0 },
418 /* 0xf1 */ { NULL, NULL, 0 },
419 /* 0xf2 */ { NULL, NULL, 0 },
420 /* 0xf3 */ { NULL, NULL, 0 },
421 /* 0xf4 */ { NULL, NULL, 0 },
422 /* 0xf5 */ { NULL, NULL, 0 },
423 /* 0xf6 */ { NULL, NULL, 0 },
424 /* 0xf7 */ { NULL, NULL, 0 },
425 /* 0xf8 */ { NULL, NULL, 0 },
426 /* 0xf9 */ { NULL, NULL, 0 },
427 /* 0xfa */ { NULL, NULL, 0 },
428 /* 0xfb */ { NULL, NULL, 0 },
429 /* 0xfc */ { NULL, NULL, 0 },
430 /* 0xfd */ { NULL, NULL, 0 },
431 /* 0xfe */ { NULL, NULL, 0 },
432 /* 0xff */ { NULL, NULL, 0 }
435 /****************************************************************************
436 return a string containing the function name of a SMB command
437 ****************************************************************************/
438 static const char *smb_fn_name(uint8_t type)
440 const char *unknown_name = "SMBunknown";
442 if (smb_messages[type].name == NULL)
445 return smb_messages[type].name;
449 /****************************************************************************
450 Do a switch on the message type and call the specific reply function for this
451 message. Unlike earlier versions of Samba the reply functions are responsible
452 for sending the reply themselves, rather than returning a size to this function
453 The reply functions may also choose to delay the processing by pushing the message
454 onto the message queue
455 ****************************************************************************/
456 static void switch_message(int type, struct smbsrv_request *req)
459 struct smbsrv_connection *smb_conn = req->smb_conn;
466 if (smb_messages[type].fn == NULL) {
467 DEBUG(0,("Unknown message type %d!\n",type));
468 smbsrv_reply_unknown(req);
472 flags = smb_messages[type].flags;
474 req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
477 /* setup the user context for this request if it
478 hasn't already been initialised (to cope with SMB
481 /* In share mode security we must ignore the vuid. */
482 if (smb_conn->config.security == SEC_SHARE) {
484 req->session = req->tcon->sec_share.session;
487 req->session = smbsrv_session_find(req->smb_conn, SVAL(req->in.hdr,HDR_UID));
491 DEBUG(5,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->server_id));
493 /* this must be called before we do any reply */
494 if (flags & SIGNING_NO_REPLY) {
495 smbsrv_signing_no_reply(req);
498 /* see if the vuid is valid */
499 if ((flags & NEED_SESS) && !req->session) {
500 /* amazingly, the error code depends on the command */
505 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
508 status = NT_STATUS_INVALID_HANDLE;
513 * don't know how to handle smb signing for this case
514 * so just skip the reply
516 if ((flags & SIGNING_NO_REPLY) &&
517 (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
518 DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
519 smb_fn_name(type), nt_errstr(status)));
523 smbsrv_send_error(req, status);
527 /* does this protocol need a valid tree connection? */
528 if ((flags & NEED_TCON) && !req->tcon) {
529 /* amazingly, the error code depends on the command */
533 status = NT_STATUS_DOS(ERRSRV, ERRinvnid);
536 status = NT_STATUS_INVALID_HANDLE;
541 * don't know how to handle smb signing for this case
542 * so just skip the reply
544 if ((flags & SIGNING_NO_REPLY) &&
545 (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
546 DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
547 smb_fn_name(type), nt_errstr(status)));
551 smbsrv_send_error(req, status);
555 smb_messages[type].fn(req);
559 we call this when first first part of a possibly chained request has been completed
560 and we need to call the 2nd part, if any
562 void smbsrv_chain_reply(struct smbsrv_request *req)
564 uint16_t chain_cmd, chain_offset;
569 if (req->in.wct < 2 || req->out.wct < 2) {
570 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
574 chain_cmd = CVAL(req->in.vwv, VWV(0));
575 chain_offset = SVAL(req->in.vwv, VWV(1));
577 if (chain_cmd == SMB_CHAIN_NONE) {
579 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
580 SSVAL(req->out.vwv, VWV(1), 0);
581 smbsrv_send_reply(req);
585 if (chain_offset + req->in.hdr >= req->in.buffer + req->in.size) {
589 wct = CVAL(req->in.hdr, chain_offset);
590 vwv = req->in.hdr + chain_offset + 1;
592 if (vwv + VWV(wct) + 2 > req->in.buffer + req->in.size) {
596 data_size = SVAL(vwv, VWV(wct));
597 data = vwv + VWV(wct) + 2;
599 if (data + data_size > req->in.buffer + req->in.size) {
603 /* all seems legit */
607 req->in.data_size = data_size;
612 SSVAL(req->out.vwv, VWV(0), chain_cmd);
613 SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
615 /* cleanup somestuff for the next request */
616 talloc_free(req->ntvfs);
618 talloc_free(req->io_ptr);
621 switch_message(chain_cmd, req);
625 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
626 SSVAL(req->out.vwv, VWV(1), 0);
627 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
631 * init the SMB protocol related stuff
633 NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn)
637 /* now initialise a few default values associated with this smb socket */
638 smb_conn->negotiate.max_send = 0xFFFF;
640 /* this is the size that w2k uses, and it appears to be important for
642 smb_conn->negotiate.max_recv = lp_max_xmit();
644 smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
646 smb_conn->config.security = lp_security();
647 smb_conn->config.nt_status_support = lp_nt_status_support();
649 status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
650 NT_STATUS_NOT_OK_RETURN(status);
652 status = smbsrv_smb_init_tcons(smb_conn);
653 NT_STATUS_NOT_OK_RETURN(status);
655 smbsrv_init_signing(smb_conn);