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 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/>.
23
#include "system/time.h"
24
#include "smbd/service_stream.h"
25
#include "smb_server/smb_server.h"
26
#include "smb_server/service_smb_proto.h"
27
#include "ntvfs/ntvfs.h"
28
#include "system/filesys.h"
29
#include "param/param.h"
33
send an oplock break request to a client
35
NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level)
37
struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon);
38
struct smbsrv_request *req;
40
req = smbsrv_init_request(tcon->smb_conn);
41
NT_STATUS_HAVE_NO_MEMORY(req);
43
smbsrv_setup_reply(req, 8, 0);
45
SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
46
SSVAL(req->out.hdr,HDR_TID,tcon->tid);
47
SSVAL(req->out.hdr,HDR_PID,0xFFFF);
48
SSVAL(req->out.hdr,HDR_UID,0);
49
SSVAL(req->out.hdr,HDR_MID,0xFFFF);
50
SCVAL(req->out.hdr,HDR_FLG,0);
51
SSVAL(req->out.hdr,HDR_FLG2,0);
53
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
54
SSVAL(req->out.vwv, VWV(1), 0);
55
smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs);
56
SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
57
SCVAL(req->out.vwv, VWV(3)+1, level);
58
SIVAL(req->out.vwv, VWV(4), 0);
59
SSVAL(req->out.vwv, VWV(6), 0);
60
SSVAL(req->out.vwv, VWV(7), 0);
62
smbsrv_send_reply(req);
66
static void switch_message(int type, struct smbsrv_request *req);
69
These flags determine some of the permissions required to do an operation
71
#define NEED_SESS (1<<0)
72
#define NEED_TCON (1<<1)
73
#define SIGNING_NO_REPLY (1<<2)
74
/* does VWV(0) of the request hold chaining information */
76
/* The 64Kb question: are requests > 64K valid? */
77
#define LARGE_REQUEST (1<<4)
80
define a list of possible SMB messages and their corresponding
81
functions. Any message that has a NULL function is unimplemented -
82
please feel free to contribute implementations!
84
static const struct smb_message_struct
87
void (*fn)(struct smbsrv_request *);
88
#define message_flags(type) smb_messages[(type) & 0xff].flags
92
/* 0x00 */ { "SMBmkdir", smbsrv_reply_mkdir, NEED_SESS|NEED_TCON },
93
/* 0x01 */ { "SMBrmdir", smbsrv_reply_rmdir, NEED_SESS|NEED_TCON },
94
/* 0x02 */ { "SMBopen", smbsrv_reply_open, NEED_SESS|NEED_TCON },
95
/* 0x03 */ { "SMBcreate", smbsrv_reply_mknew, NEED_SESS|NEED_TCON },
96
/* 0x04 */ { "SMBclose", smbsrv_reply_close, NEED_SESS|NEED_TCON },
97
/* 0x05 */ { "SMBflush", smbsrv_reply_flush, NEED_SESS|NEED_TCON },
98
/* 0x06 */ { "SMBunlink", smbsrv_reply_unlink, NEED_SESS|NEED_TCON },
99
/* 0x07 */ { "SMBmv", smbsrv_reply_mv, NEED_SESS|NEED_TCON },
100
/* 0x08 */ { "SMBgetatr", smbsrv_reply_getatr, NEED_SESS|NEED_TCON },
101
/* 0x09 */ { "SMBsetatr", smbsrv_reply_setatr, NEED_SESS|NEED_TCON },
102
/* 0x0a */ { "SMBread", smbsrv_reply_read, NEED_SESS|NEED_TCON },
103
/* 0x0b */ { "SMBwrite", smbsrv_reply_write, NEED_SESS|NEED_TCON },
104
/* 0x0c */ { "SMBlock", smbsrv_reply_lock, NEED_SESS|NEED_TCON },
105
/* 0x0d */ { "SMBunlock", smbsrv_reply_unlock, NEED_SESS|NEED_TCON },
106
/* 0x0e */ { "SMBctemp", smbsrv_reply_ctemp, NEED_SESS|NEED_TCON },
107
/* 0x0f */ { "SMBmknew", smbsrv_reply_mknew, NEED_SESS|NEED_TCON },
108
/* 0x10 */ { "SMBchkpth", smbsrv_reply_chkpth, NEED_SESS|NEED_TCON },
109
/* 0x11 */ { "SMBexit", smbsrv_reply_exit, NEED_SESS },
110
/* 0x12 */ { "SMBlseek", smbsrv_reply_lseek, NEED_SESS|NEED_TCON },
111
/* 0x13 */ { "SMBlockread", smbsrv_reply_lockread, NEED_SESS|NEED_TCON },
112
/* 0x14 */ { "SMBwriteunlock", smbsrv_reply_writeunlock, NEED_SESS|NEED_TCON },
113
/* 0x15 */ { NULL, NULL, 0 },
114
/* 0x16 */ { NULL, NULL, 0 },
115
/* 0x17 */ { NULL, NULL, 0 },
116
/* 0x18 */ { NULL, NULL, 0 },
117
/* 0x19 */ { NULL, NULL, 0 },
118
/* 0x1a */ { "SMBreadbraw", smbsrv_reply_readbraw, NEED_SESS|NEED_TCON },
119
/* 0x1b */ { "SMBreadBmpx", smbsrv_reply_readbmpx, NEED_SESS|NEED_TCON },
120
/* 0x1c */ { "SMBreadBs", NULL, 0 },
121
/* 0x1d */ { "SMBwritebraw", smbsrv_reply_writebraw, NEED_SESS|NEED_TCON },
122
/* 0x1e */ { "SMBwriteBmpx", smbsrv_reply_writebmpx, NEED_SESS|NEED_TCON },
123
/* 0x1f */ { "SMBwriteBs", smbsrv_reply_writebs, NEED_SESS|NEED_TCON },
124
/* 0x20 */ { "SMBwritec", NULL, 0 },
125
/* 0x21 */ { NULL, NULL, 0 },
126
/* 0x22 */ { "SMBsetattrE", smbsrv_reply_setattrE, NEED_SESS|NEED_TCON },
127
/* 0x23 */ { "SMBgetattrE", smbsrv_reply_getattrE, NEED_SESS|NEED_TCON },
128
/* 0x24 */ { "SMBlockingX", smbsrv_reply_lockingX, NEED_SESS|NEED_TCON|AND_X },
129
/* 0x25 */ { "SMBtrans", smbsrv_reply_trans, NEED_SESS|NEED_TCON },
130
/* 0x26 */ { "SMBtranss", smbsrv_reply_transs, NEED_SESS|NEED_TCON },
131
/* 0x27 */ { "SMBioctl", smbsrv_reply_ioctl, NEED_SESS|NEED_TCON },
132
/* 0x28 */ { "SMBioctls", NULL, NEED_SESS|NEED_TCON },
133
/* 0x29 */ { "SMBcopy", smbsrv_reply_copy, NEED_SESS|NEED_TCON },
134
/* 0x2a */ { "SMBmove", NULL, NEED_SESS|NEED_TCON },
135
/* 0x2b */ { "SMBecho", smbsrv_reply_echo, 0 },
136
/* 0x2c */ { "SMBwriteclose", smbsrv_reply_writeclose, NEED_SESS|NEED_TCON },
137
/* 0x2d */ { "SMBopenX", smbsrv_reply_open_and_X, NEED_SESS|NEED_TCON|AND_X },
138
/* 0x2e */ { "SMBreadX", smbsrv_reply_read_and_X, NEED_SESS|NEED_TCON|AND_X },
139
/* 0x2f */ { "SMBwriteX", smbsrv_reply_write_and_X, NEED_SESS|NEED_TCON|AND_X|LARGE_REQUEST},
140
/* 0x30 */ { NULL, NULL, 0 },
141
/* 0x31 */ { NULL, NULL, 0 },
142
/* 0x32 */ { "SMBtrans2", smbsrv_reply_trans2, NEED_SESS|NEED_TCON },
143
/* 0x33 */ { "SMBtranss2", smbsrv_reply_transs2, NEED_SESS|NEED_TCON },
144
/* 0x34 */ { "SMBfindclose", smbsrv_reply_findclose, NEED_SESS|NEED_TCON },
145
/* 0x35 */ { "SMBfindnclose", smbsrv_reply_findnclose, NEED_SESS|NEED_TCON },
146
/* 0x36 */ { NULL, NULL, 0 },
147
/* 0x37 */ { NULL, NULL, 0 },
148
/* 0x38 */ { NULL, NULL, 0 },
149
/* 0x39 */ { NULL, NULL, 0 },
150
/* 0x3a */ { NULL, NULL, 0 },
151
/* 0x3b */ { NULL, NULL, 0 },
152
/* 0x3c */ { NULL, NULL, 0 },
153
/* 0x3d */ { NULL, NULL, 0 },
154
/* 0x3e */ { NULL, NULL, 0 },
155
/* 0x3f */ { NULL, NULL, 0 },
156
/* 0x40 */ { NULL, NULL, 0 },
157
/* 0x41 */ { NULL, NULL, 0 },
158
/* 0x42 */ { NULL, NULL, 0 },
159
/* 0x43 */ { NULL, NULL, 0 },
160
/* 0x44 */ { NULL, NULL, 0 },
161
/* 0x45 */ { NULL, NULL, 0 },
162
/* 0x46 */ { NULL, NULL, 0 },
163
/* 0x47 */ { NULL, NULL, 0 },
164
/* 0x48 */ { NULL, NULL, 0 },
165
/* 0x49 */ { NULL, NULL, 0 },
166
/* 0x4a */ { NULL, NULL, 0 },
167
/* 0x4b */ { NULL, NULL, 0 },
168
/* 0x4c */ { NULL, NULL, 0 },
169
/* 0x4d */ { NULL, NULL, 0 },
170
/* 0x4e */ { NULL, NULL, 0 },
171
/* 0x4f */ { NULL, NULL, 0 },
172
/* 0x50 */ { NULL, NULL, 0 },
173
/* 0x51 */ { NULL, NULL, 0 },
174
/* 0x52 */ { NULL, NULL, 0 },
175
/* 0x53 */ { NULL, NULL, 0 },
176
/* 0x54 */ { NULL, NULL, 0 },
177
/* 0x55 */ { NULL, NULL, 0 },
178
/* 0x56 */ { NULL, NULL, 0 },
179
/* 0x57 */ { NULL, NULL, 0 },
180
/* 0x58 */ { NULL, NULL, 0 },
181
/* 0x59 */ { NULL, NULL, 0 },
182
/* 0x5a */ { NULL, NULL, 0 },
183
/* 0x5b */ { NULL, NULL, 0 },
184
/* 0x5c */ { NULL, NULL, 0 },
185
/* 0x5d */ { NULL, NULL, 0 },
186
/* 0x5e */ { NULL, NULL, 0 },
187
/* 0x5f */ { NULL, NULL, 0 },
188
/* 0x60 */ { NULL, NULL, 0 },
189
/* 0x61 */ { NULL, NULL, 0 },
190
/* 0x62 */ { NULL, NULL, 0 },
191
/* 0x63 */ { NULL, NULL, 0 },
192
/* 0x64 */ { NULL, NULL, 0 },
193
/* 0x65 */ { NULL, NULL, 0 },
194
/* 0x66 */ { NULL, NULL, 0 },
195
/* 0x67 */ { NULL, NULL, 0 },
196
/* 0x68 */ { NULL, NULL, 0 },
197
/* 0x69 */ { NULL, NULL, 0 },
198
/* 0x6a */ { NULL, NULL, 0 },
199
/* 0x6b */ { NULL, NULL, 0 },
200
/* 0x6c */ { NULL, NULL, 0 },
201
/* 0x6d */ { NULL, NULL, 0 },
202
/* 0x6e */ { NULL, NULL, 0 },
203
/* 0x6f */ { NULL, NULL, 0 },
204
/* 0x70 */ { "SMBtcon", smbsrv_reply_tcon, NEED_SESS },
205
/* 0x71 */ { "SMBtdis", smbsrv_reply_tdis, NEED_TCON },
206
/* 0x72 */ { "SMBnegprot", smbsrv_reply_negprot, 0 },
207
/* 0x73 */ { "SMBsesssetupX", smbsrv_reply_sesssetup, AND_X },
208
/* 0x74 */ { "SMBulogoffX", smbsrv_reply_ulogoffX, NEED_SESS|AND_X }, /* ulogoff doesn't give a valid TID */
209
/* 0x75 */ { "SMBtconX", smbsrv_reply_tcon_and_X, NEED_SESS|AND_X },
210
/* 0x76 */ { NULL, NULL, 0 },
211
/* 0x77 */ { NULL, NULL, 0 },
212
/* 0x78 */ { NULL, NULL, 0 },
213
/* 0x79 */ { NULL, NULL, 0 },
214
/* 0x7a */ { NULL, NULL, 0 },
215
/* 0x7b */ { NULL, NULL, 0 },
216
/* 0x7c */ { NULL, NULL, 0 },
217
/* 0x7d */ { NULL, NULL, 0 },
218
/* 0x7e */ { NULL, NULL, 0 },
219
/* 0x7f */ { NULL, NULL, 0 },
220
/* 0x80 */ { "SMBdskattr", smbsrv_reply_dskattr, NEED_SESS|NEED_TCON },
221
/* 0x81 */ { "SMBsearch", smbsrv_reply_search, NEED_SESS|NEED_TCON },
222
/* 0x82 */ { "SMBffirst", smbsrv_reply_search, NEED_SESS|NEED_TCON },
223
/* 0x83 */ { "SMBfunique", smbsrv_reply_search, NEED_SESS|NEED_TCON },
224
/* 0x84 */ { "SMBfclose", smbsrv_reply_fclose, NEED_SESS|NEED_TCON },
225
/* 0x85 */ { NULL, NULL, 0 },
226
/* 0x86 */ { NULL, NULL, 0 },
227
/* 0x87 */ { NULL, NULL, 0 },
228
/* 0x88 */ { NULL, NULL, 0 },
229
/* 0x89 */ { NULL, NULL, 0 },
230
/* 0x8a */ { NULL, NULL, 0 },
231
/* 0x8b */ { NULL, NULL, 0 },
232
/* 0x8c */ { NULL, NULL, 0 },
233
/* 0x8d */ { NULL, NULL, 0 },
234
/* 0x8e */ { NULL, NULL, 0 },
235
/* 0x8f */ { NULL, NULL, 0 },
236
/* 0x90 */ { NULL, NULL, 0 },
237
/* 0x91 */ { NULL, NULL, 0 },
238
/* 0x92 */ { NULL, NULL, 0 },
239
/* 0x93 */ { NULL, NULL, 0 },
240
/* 0x94 */ { NULL, NULL, 0 },
241
/* 0x95 */ { NULL, NULL, 0 },
242
/* 0x96 */ { NULL, NULL, 0 },
243
/* 0x97 */ { NULL, NULL, 0 },
244
/* 0x98 */ { NULL, NULL, 0 },
245
/* 0x99 */ { NULL, NULL, 0 },
246
/* 0x9a */ { NULL, NULL, 0 },
247
/* 0x9b */ { NULL, NULL, 0 },
248
/* 0x9c */ { NULL, NULL, 0 },
249
/* 0x9d */ { NULL, NULL, 0 },
250
/* 0x9e */ { NULL, NULL, 0 },
251
/* 0x9f */ { NULL, NULL, 0 },
252
/* 0xa0 */ { "SMBnttrans", smbsrv_reply_nttrans, NEED_SESS|NEED_TCON|LARGE_REQUEST },
253
/* 0xa1 */ { "SMBnttranss", smbsrv_reply_nttranss, NEED_SESS|NEED_TCON },
254
/* 0xa2 */ { "SMBntcreateX", smbsrv_reply_ntcreate_and_X, NEED_SESS|NEED_TCON|AND_X },
255
/* 0xa3 */ { NULL, NULL, 0 },
256
/* 0xa4 */ { "SMBntcancel", smbsrv_reply_ntcancel, NEED_SESS|NEED_TCON|SIGNING_NO_REPLY },
257
/* 0xa5 */ { "SMBntrename", smbsrv_reply_ntrename, NEED_SESS|NEED_TCON },
258
/* 0xa6 */ { NULL, NULL, 0 },
259
/* 0xa7 */ { NULL, NULL, 0 },
260
/* 0xa8 */ { NULL, NULL, 0 },
261
/* 0xa9 */ { NULL, NULL, 0 },
262
/* 0xaa */ { NULL, NULL, 0 },
263
/* 0xab */ { NULL, NULL, 0 },
264
/* 0xac */ { NULL, NULL, 0 },
265
/* 0xad */ { NULL, NULL, 0 },
266
/* 0xae */ { NULL, NULL, 0 },
267
/* 0xaf */ { NULL, NULL, 0 },
268
/* 0xb0 */ { NULL, NULL, 0 },
269
/* 0xb1 */ { NULL, NULL, 0 },
270
/* 0xb2 */ { NULL, NULL, 0 },
271
/* 0xb3 */ { NULL, NULL, 0 },
272
/* 0xb4 */ { NULL, NULL, 0 },
273
/* 0xb5 */ { NULL, NULL, 0 },
274
/* 0xb6 */ { NULL, NULL, 0 },
275
/* 0xb7 */ { NULL, NULL, 0 },
276
/* 0xb8 */ { NULL, NULL, 0 },
277
/* 0xb9 */ { NULL, NULL, 0 },
278
/* 0xba */ { NULL, NULL, 0 },
279
/* 0xbb */ { NULL, NULL, 0 },
280
/* 0xbc */ { NULL, NULL, 0 },
281
/* 0xbd */ { NULL, NULL, 0 },
282
/* 0xbe */ { NULL, NULL, 0 },
283
/* 0xbf */ { NULL, NULL, 0 },
284
/* 0xc0 */ { "SMBsplopen", smbsrv_reply_printopen, NEED_SESS|NEED_TCON },
285
/* 0xc1 */ { "SMBsplwr", smbsrv_reply_printwrite, NEED_SESS|NEED_TCON },
286
/* 0xc2 */ { "SMBsplclose", smbsrv_reply_printclose, NEED_SESS|NEED_TCON },
287
/* 0xc3 */ { "SMBsplretq", smbsrv_reply_printqueue, NEED_SESS|NEED_TCON },
288
/* 0xc4 */ { NULL, NULL, 0 },
289
/* 0xc5 */ { NULL, NULL, 0 },
290
/* 0xc6 */ { NULL, NULL, 0 },
291
/* 0xc7 */ { NULL, NULL, 0 },
292
/* 0xc8 */ { NULL, NULL, 0 },
293
/* 0xc9 */ { NULL, NULL, 0 },
294
/* 0xca */ { NULL, NULL, 0 },
295
/* 0xcb */ { NULL, NULL, 0 },
296
/* 0xcc */ { NULL, NULL, 0 },
297
/* 0xcd */ { NULL, NULL, 0 },
298
/* 0xce */ { NULL, NULL, 0 },
299
/* 0xcf */ { NULL, NULL, 0 },
300
/* 0xd0 */ { "SMBsends", NULL, 0 },
301
/* 0xd1 */ { "SMBsendb", NULL, 0 },
302
/* 0xd2 */ { "SMBfwdname", NULL, 0 },
303
/* 0xd3 */ { "SMBcancelf", NULL, 0 },
304
/* 0xd4 */ { "SMBgetmac", NULL, 0 },
305
/* 0xd5 */ { "SMBsendstrt", NULL, 0 },
306
/* 0xd6 */ { "SMBsendend", NULL, 0 },
307
/* 0xd7 */ { "SMBsendtxt", NULL, 0 },
308
/* 0xd8 */ { NULL, NULL, 0 },
309
/* 0xd9 */ { NULL, NULL, 0 },
310
/* 0xda */ { NULL, NULL, 0 },
311
/* 0xdb */ { NULL, NULL, 0 },
312
/* 0xdc */ { NULL, NULL, 0 },
313
/* 0xdd */ { NULL, NULL, 0 },
314
/* 0xde */ { NULL, NULL, 0 },
315
/* 0xdf */ { NULL, NULL, 0 },
316
/* 0xe0 */ { NULL, NULL, 0 },
317
/* 0xe1 */ { NULL, NULL, 0 },
318
/* 0xe2 */ { NULL, NULL, 0 },
319
/* 0xe3 */ { NULL, NULL, 0 },
320
/* 0xe4 */ { NULL, NULL, 0 },
321
/* 0xe5 */ { NULL, NULL, 0 },
322
/* 0xe6 */ { NULL, NULL, 0 },
323
/* 0xe7 */ { NULL, NULL, 0 },
324
/* 0xe8 */ { NULL, NULL, 0 },
325
/* 0xe9 */ { NULL, NULL, 0 },
326
/* 0xea */ { NULL, NULL, 0 },
327
/* 0xeb */ { NULL, NULL, 0 },
328
/* 0xec */ { NULL, NULL, 0 },
329
/* 0xed */ { NULL, NULL, 0 },
330
/* 0xee */ { NULL, NULL, 0 },
331
/* 0xef */ { NULL, NULL, 0 },
332
/* 0xf0 */ { NULL, NULL, 0 },
333
/* 0xf1 */ { NULL, NULL, 0 },
334
/* 0xf2 */ { NULL, NULL, 0 },
335
/* 0xf3 */ { NULL, NULL, 0 },
336
/* 0xf4 */ { NULL, NULL, 0 },
337
/* 0xf5 */ { NULL, NULL, 0 },
338
/* 0xf6 */ { NULL, NULL, 0 },
339
/* 0xf7 */ { NULL, NULL, 0 },
340
/* 0xf8 */ { NULL, NULL, 0 },
341
/* 0xf9 */ { NULL, NULL, 0 },
342
/* 0xfa */ { NULL, NULL, 0 },
343
/* 0xfb */ { NULL, NULL, 0 },
344
/* 0xfc */ { NULL, NULL, 0 },
345
/* 0xfd */ { NULL, NULL, 0 },
346
/* 0xfe */ { NULL, NULL, 0 },
347
/* 0xff */ { NULL, NULL, 0 }
350
/****************************************************************************
351
receive a SMB request header from the wire, forming a request_context
353
****************************************************************************/
354
NTSTATUS smbsrv_recv_smb_request(void *private_data, DATA_BLOB blob)
356
struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
357
struct smbsrv_request *req;
358
struct timeval cur_time = timeval_current();
361
smb_conn->statistics.last_request_time = cur_time;
363
/* see if its a special NBT packet */
364
if (CVAL(blob.data, 0) != 0) {
365
req = smbsrv_init_request(smb_conn);
366
NT_STATUS_HAVE_NO_MEMORY(req);
368
ZERO_STRUCT(req->in);
370
req->in.buffer = talloc_steal(req, blob.data);
371
req->in.size = blob.length;
372
req->request_time = cur_time;
374
smbsrv_reply_special(req);
378
if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) {
379
DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length));
380
smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
384
/* Make sure this is an SMB packet */
385
if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) {
386
DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n",
388
smbsrv_terminate_connection(smb_conn, "Non-SMB packet");
392
req = smbsrv_init_request(smb_conn);
393
NT_STATUS_HAVE_NO_MEMORY(req);
395
req->in.buffer = talloc_steal(req, blob.data);
396
req->in.size = blob.length;
397
req->request_time = cur_time;
398
req->chained_fnum = -1;
399
req->in.allocated = req->in.size;
400
req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
401
req->in.vwv = req->in.hdr + HDR_VWV;
402
req->in.wct = CVAL(req->in.hdr, HDR_WCT);
404
command = CVAL(req->in.hdr, HDR_COM);
406
if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) {
407
req->in.data = req->in.vwv + VWV(req->in.wct) + 2;
408
req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
410
/* the bcc length is only 16 bits, but some packets
411
(such as SMBwriteX) can be much larger than 64k. We
412
detect this by looking for a large non-chained NBT
413
packet (at least 64k bigger than what is
414
specified). If it is detected then the NBT size is
415
used instead of the bcc size */
416
if (req->in.data_size + 0x10000 <=
417
req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
418
( message_flags(command) & LARGE_REQUEST) &&
419
( !(message_flags(command) & AND_X) ||
420
(req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) )
422
/* its an oversized packet! fun for all the family */
423
req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
427
if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) {
428
DEBUG(2,("Invalid SMB word count %d\n", req->in.wct));
429
smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
433
if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) {
434
DEBUG(2,("Invalid SMB buffer length count %d\n",
435
(int)req->in.data_size));
436
smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
440
req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
442
/* fix the bufinfo */
443
smbsrv_setup_bufinfo(req);
445
if (!smbsrv_signing_check_incoming(req)) {
446
smbsrv_send_error(req, NT_STATUS_ACCESS_DENIED);
450
command = CVAL(req->in.hdr, HDR_COM);
451
switch_message(command, req);
455
/****************************************************************************
456
return a string containing the function name of a SMB command
457
****************************************************************************/
458
static const char *smb_fn_name(uint8_t type)
460
const char *unknown_name = "SMBunknown";
462
if (smb_messages[type].name == NULL)
465
return smb_messages[type].name;
469
/****************************************************************************
470
Do a switch on the message type and call the specific reply function for this
471
message. Unlike earlier versions of Samba the reply functions are responsible
472
for sending the reply themselves, rather than returning a size to this function
473
The reply functions may also choose to delay the processing by pushing the message
474
onto the message queue
475
****************************************************************************/
476
static void switch_message(int type, struct smbsrv_request *req)
479
struct smbsrv_connection *smb_conn = req->smb_conn;
486
if (smb_messages[type].fn == NULL) {
487
DEBUG(0,("Unknown message type %d!\n",type));
488
smbsrv_reply_unknown(req);
492
flags = smb_messages[type].flags;
494
req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID), req->request_time);
497
/* setup the user context for this request if it
498
hasn't already been initialised (to cope with SMB
501
/* In share mode security we must ignore the vuid. */
502
if (smb_conn->config.security == SEC_SHARE) {
504
req->session = req->tcon->sec_share.session;
507
req->session = smbsrv_session_find(req->smb_conn, SVAL(req->in.hdr,HDR_UID), req->request_time);
511
DEBUG(5,("switch message %s (task_id %u)\n",
512
smb_fn_name(type), (unsigned)req->smb_conn->connection->server_id.id));
514
/* this must be called before we do any reply */
515
if (flags & SIGNING_NO_REPLY) {
516
smbsrv_signing_no_reply(req);
519
/* see if the vuid is valid */
520
if ((flags & NEED_SESS) && !req->session) {
521
status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
522
/* amazingly, the error code depends on the command */
529
if (req->smb_conn->config.nt_status_support &&
530
req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
531
status = NT_STATUS_INVALID_HANDLE;
537
* don't know how to handle smb signing for this case
538
* so just skip the reply
540
if ((flags & SIGNING_NO_REPLY) &&
541
(req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
542
DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
543
smb_fn_name(type), nt_errstr(status)));
547
smbsrv_send_error(req, status);
551
/* does this protocol need a valid tree connection? */
552
if ((flags & NEED_TCON) && !req->tcon) {
553
status = NT_STATUS_DOS(ERRSRV, ERRinvnid);
554
/* amazingly, the error code depends on the command */
561
if (req->smb_conn->config.nt_status_support &&
562
req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
563
status = NT_STATUS_INVALID_HANDLE;
569
* don't know how to handle smb signing for this case
570
* so just skip the reply
572
if ((flags & SIGNING_NO_REPLY) &&
573
(req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
574
DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
575
smb_fn_name(type), nt_errstr(status)));
579
smbsrv_send_error(req, status);
583
smb_messages[type].fn(req);
587
we call this when first first part of a possibly chained request has been completed
588
and we need to call the 2nd part, if any
590
void smbsrv_chain_reply(struct smbsrv_request *req)
592
uint16_t chain_cmd, chain_offset;
597
if (req->in.wct < 2 || req->out.wct < 2) {
598
smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
602
chain_cmd = CVAL(req->in.vwv, VWV(0));
603
chain_offset = SVAL(req->in.vwv, VWV(1));
605
if (chain_cmd == SMB_CHAIN_NONE) {
607
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
608
SSVAL(req->out.vwv, VWV(1), 0);
609
smbsrv_send_reply(req);
613
if (chain_offset + req->in.hdr >= req->in.buffer + req->in.size) {
617
wct = CVAL(req->in.hdr, chain_offset);
618
vwv = req->in.hdr + chain_offset + 1;
620
if (vwv + VWV(wct) + 2 > req->in.buffer + req->in.size) {
624
data_size = SVAL(vwv, VWV(wct));
625
data = vwv + VWV(wct) + 2;
627
if (data + data_size > req->in.buffer + req->in.size) {
631
/* all seems legit */
635
req->in.data_size = data_size;
638
/* fix the bufinfo */
639
smbsrv_setup_bufinfo(req);
643
SSVAL(req->out.vwv, VWV(0), chain_cmd);
644
SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
646
/* cleanup somestuff for the next request */
647
talloc_free(req->ntvfs);
649
talloc_free(req->io_ptr);
652
switch_message(chain_cmd, req);
656
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
657
SSVAL(req->out.vwv, VWV(1), 0);
658
smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
662
* init the SMB protocol related stuff
664
NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn, struct loadparm_context *lp_ctx)
668
/* now initialise a few default values associated with this smb socket */
669
smb_conn->negotiate.max_send = 0xFFFF;
671
/* this is the size that w2k uses, and it appears to be important for
673
smb_conn->negotiate.max_recv = lp_max_xmit(lp_ctx);
675
smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
677
smb_conn->config.security = lp_security(lp_ctx);
678
smb_conn->config.nt_status_support = lp_nt_status_support(lp_ctx);
680
status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
681
NT_STATUS_NOT_OK_RETURN(status);
683
status = smbsrv_smb_init_tcons(smb_conn);
684
NT_STATUS_NOT_OK_RETURN(status);
686
smbsrv_init_signing(smb_conn);