1 /*
2 Unix SMB/CIFS mplementation.
3
4 helper layer for breaking up streams into discrete requests
5
6 Copyright (C) Andrew Tridgell 2005
7
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.
12
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.
17
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.
21
22 */
23
24 #include "includes.h"
25 #include "lib/util/dlinklist.h"
26 #include "lib/events/events.h"
27 #include "lib/socket/socket.h"
28 #include "lib/stream/packet.h"
29 #include "libcli/raw/smb.h"
30
31 struct packet_context {
32 packet_callback_fn_t callback;
33 packet_full_request_fn_t full_request;
34 packet_error_handler_fn_t error_handler;
35 DATA_BLOB partial;
36 uint32_t num_read;
37 uint32_t initial_read;
38 struct socket_context *sock;
39 struct event_context *ev;
40 size_t packet_size;
41 void *private;
42 struct fd_event *fde;
43 BOOL serialise;
44 int processing;
45 BOOL recv_disable;
46 BOOL nofree;
47
48 BOOL busy;
49 BOOL destructor_called;
50
51 struct send_element {
52 struct send_element *next, *prev;
53 DATA_BLOB blob;
54 size_t nsent;
55 packet_send_callback_fn_t send_callback;
56 void *send_callback_private;
57 } *send_queue;
58 };
59
60 /*
61 a destructor used when we are processing packets to prevent freeing of this
62 context while it is being used
63 */
packet_destructor(struct packet_context * pc)64 static int packet_destructor(struct packet_context *pc)
65 {
66 if (pc->busy) {
67 pc->destructor_called = True;
68 /* now we refuse the talloc_free() request. The free will
69 happen again in the packet_recv() code */
70 return -1;
71 }
72
73 return 0;
74 }
75
76
77 /*
78 initialise a packet receiver
79 */
packet_init(TALLOC_CTX * mem_ctx)80 _PUBLIC_ struct packet_context *packet_init(TALLOC_CTX *mem_ctx)
81 {
82 struct packet_context *pc = talloc_zero(mem_ctx, struct packet_context);
83 if (pc != NULL) {
84 talloc_set_destructor(pc, packet_destructor);
85 }
86 return pc;
87 }
88
89
90 /*
91 set the request callback, called when a full request is ready
92 */
packet_set_callback(struct packet_context * pc,packet_callback_fn_t callback)93 _PUBLIC_ void packet_set_callback(struct packet_context *pc, packet_callback_fn_t callback)
94 {
95 pc->callback = callback;
96 }
97
98 /*
99 set the error handler
100 */
packet_set_error_handler(struct packet_context * pc,packet_error_handler_fn_t handler)101 _PUBLIC_ void packet_set_error_handler(struct packet_context *pc, packet_error_handler_fn_t handler)
102 {
103 pc->error_handler = handler;
104 }
105
106 /*
107 set the private pointer passed to the callback functions
108 */
packet_set_private(struct packet_context * pc,void * private)109 _PUBLIC_ void packet_set_private(struct packet_context *pc, void *private)
110 {
111 pc->private = private;
112 }
113
114 /*
115 set the full request callback. Should return as follows:
116 NT_STATUS_OK == blob is a full request.
117 STATUS_MORE_ENTRIES == blob is not complete yet
118 any error == blob is not a valid
119 */
packet_set_full_request(struct packet_context * pc,packet_full_request_fn_t callback)120 _PUBLIC_ void packet_set_full_request(struct packet_context *pc, packet_full_request_fn_t callback)
121 {
122 pc->full_request = callback;
123 }
124
125 /*
126 set a socket context to use. You must set a socket_context
127 */
packet_set_socket(struct packet_context * pc,struct socket_context * sock)128 _PUBLIC_ void packet_set_socket(struct packet_context *pc, struct socket_context *sock)
129 {
130 pc->sock = sock;
131 }
132
133 /*
134 set an event context. If this is set then the code will ensure that
135 packets arrive with separate events, by creating a immediate event
136 for any secondary packets when more than one packet is read at one
137 time on a socket. This can matter for code that relies on not
138 getting more than one packet per event
139 */
packet_set_event_context(struct packet_context * pc,struct event_context * ev)140 _PUBLIC_ void packet_set_event_context(struct packet_context *pc, struct event_context *ev)
141 {
142 pc->ev = ev;
143 }
144
145 /*
146 tell the packet layer the fde for the socket
147 */
packet_set_fde(struct packet_context * pc,struct fd_event * fde)148 _PUBLIC_ void packet_set_fde(struct packet_context *pc, struct fd_event *fde)
149 {
150 pc->fde = fde;
151 }
152
153 /*
154 tell the packet layer to serialise requests, so we don't process two
155 requests at once on one connection. You must have set the
156 event_context and fde
157 */
packet_set_serialise(struct packet_context * pc)158 _PUBLIC_ void packet_set_serialise(struct packet_context *pc)
159 {
160 pc->serialise = True;
161 }
162
163 /*
164 tell the packet layer how much to read when starting a new packet
165 this ensures it doesn't overread
166 */
packet_set_initial_read(struct packet_context * pc,uint32_t initial_read)167 _PUBLIC_ void packet_set_initial_read(struct packet_context *pc, uint32_t initial_read)
168 {
169 pc->initial_read = initial_read;
170 }
171
172 /*
173 tell the packet system not to steal/free blobs given to packet_send()
174 */
packet_set_nofree(struct packet_context * pc)175 _PUBLIC_ void packet_set_nofree(struct packet_context *pc)
176 {
177 pc->nofree = True;
178 }
179
180
181 /*
182 tell the caller we have an error
183 */
packet_error(struct packet_context * pc,NTSTATUS status)184 static void packet_error(struct packet_context *pc, NTSTATUS status)
185 {
186 pc->sock = NULL;
187 if (pc->error_handler) {
188 pc->error_handler(pc->private, status);
189 return;
190 }
191 /* default error handler is to free the callers private pointer */
192 if (!NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
193 DEBUG(0,("packet_error on %s - %s\n",
194 talloc_get_name(pc->private), nt_errstr(status)));
195 }
196 talloc_free(pc->private);
197 return;
198 }
199
200
201 /*
202 tell the caller we have EOF
203 */
packet_eof(struct packet_context * pc)204 static void packet_eof(struct packet_context *pc)
205 {
206 packet_error(pc, NT_STATUS_END_OF_FILE);
207 }
208
209
210 /*
211 used to put packets on event boundaries
212 */
packet_next_event(struct event_context * ev,struct timed_event * te,struct timeval t,void * private)213 static void packet_next_event(struct event_context *ev, struct timed_event *te,
214 struct timeval t, void *private)
215 {
216 struct packet_context *pc = talloc_get_type(private, struct packet_context);
217 if (pc->num_read != 0 && pc->packet_size != 0 &&
218 pc->packet_size <= pc->num_read) {
219 packet_recv(pc);
220 }
221 }
222
223
224 /*
225 call this when the socket becomes readable to kick off the whole
226 stream parsing process
227 */
packet_recv(struct packet_context * pc)228 _PUBLIC_ void packet_recv(struct packet_context *pc)
229 {
230 size_t npending;
231 NTSTATUS status;
232 size_t nread = 0;
233 DATA_BLOB blob;
234
235 if (pc->processing) {
236 EVENT_FD_NOT_READABLE(pc->fde);
237 pc->processing++;
238 return;
239 }
240
241 if (pc->recv_disable) {
242 EVENT_FD_NOT_READABLE(pc->fde);
243 return;
244 }
245
246 if (pc->packet_size != 0 && pc->num_read >= pc->packet_size) {
247 goto next_partial;
248 }
249
250 if (pc->packet_size != 0) {
251 /* we've already worked out how long this next packet is, so skip the
252 socket_pending() call */
253 npending = pc->packet_size - pc->num_read;
254 } else if (pc->initial_read != 0) {
255 npending = pc->initial_read - pc->num_read;
256 } else {
257 if (pc->sock) {
258 status = socket_pending(pc->sock, &npending);
259 } else {
260 status = NT_STATUS_CONNECTION_DISCONNECTED;
261 }
262 if (!NT_STATUS_IS_OK(status)) {
263 packet_error(pc, status);
264 return;
265 }
266 }
267
268 if (npending == 0) {
269 packet_eof(pc);
270 return;
271 }
272
273 if (npending + pc->num_read < npending) {
274 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
275 return;
276 }
277
278 if (npending + pc->num_read < pc->num_read) {
279 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
280 return;
281 }
282
283 /* possibly expand the partial packet buffer */
284 if (npending + pc->num_read > pc->partial.length) {
285 status = data_blob_realloc(pc, &pc->partial, npending+pc->num_read);
286 if (!NT_STATUS_IS_OK(status)) {
287 packet_error(pc, status);
288 return;
289 }
290 }
291
292 if (pc->partial.length < pc->num_read + npending) {
293 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
294 return;
295 }
296
297 if ((uint8_t *)pc->partial.data + pc->num_read < (uint8_t *)pc->partial.data) {
298 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
299 return;
300 }
301 if ((uint8_t *)pc->partial.data + pc->num_read + npending < (uint8_t *)pc->partial.data) {
302 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
303 return;
304 }
305
306 status = socket_recv(pc->sock, pc->partial.data + pc->num_read,
307 npending, &nread);
308
309 if (NT_STATUS_IS_ERR(status)) {
310 packet_error(pc, status);
311 return;
312 }
313 if (!NT_STATUS_IS_OK(status)) {
314 return;
315 }
316
317 if (nread == 0) {
318 packet_eof(pc);
319 return;
320 }
321
322 pc->num_read += nread;
323
324 next_partial:
325 if (pc->partial.length != pc->num_read) {
326 status = data_blob_realloc(pc, &pc->partial, pc->num_read);
327 if (!NT_STATUS_IS_OK(status)) {
328 packet_error(pc, status);
329 return;
330 }
331 }
332
333 /* see if its a full request */
334 blob = pc->partial;
335 blob.length = pc->num_read;
336 status = pc->full_request(pc->private, blob, &pc->packet_size);
337 if (NT_STATUS_IS_ERR(status)) {
338 packet_error(pc, status);
339 return;
340 }
341 if (!NT_STATUS_IS_OK(status)) {
342 return;
343 }
344
345 if (pc->packet_size > pc->num_read) {
346 /* the caller made an error */
347 DEBUG(0,("Invalid packet_size %lu greater than num_read %lu\n",
348 (long)pc->packet_size, (long)pc->num_read));
349 packet_error(pc, NT_STATUS_INVALID_PARAMETER);
350 return;
351 }
352
353 /* it is a full request - give it to the caller */
354 blob = pc->partial;
355 blob.length = pc->num_read;
356
357 if (pc->packet_size < pc->num_read) {
358 pc->partial = data_blob_talloc(pc, blob.data + pc->packet_size,
359 pc->num_read - pc->packet_size);
360 if (pc->partial.data == NULL) {
361 packet_error(pc, NT_STATUS_NO_MEMORY);
362 return;
363 }
364 /* Trunate the blob sent to the caller to only the packet length */
365 status = data_blob_realloc(pc, &blob, pc->packet_size);
366 if (!NT_STATUS_IS_OK(status)) {
367 packet_error(pc, status);
368 return;
369 }
370 } else {
371 pc->partial = data_blob(NULL, 0);
372 }
373 pc->num_read -= pc->packet_size;
374 pc->packet_size = 0;
375
376 if (pc->serialise) {
377 pc->processing = 1;
378 }
379
380 pc->busy = True;
381
382 status = pc->callback(pc->private, blob);
383
384 pc->busy = False;
385
386 if (pc->destructor_called) {
387 talloc_free(pc);
388 return;
389 }
390
391 if (pc->processing) {
392 if (pc->processing > 1) {
393 EVENT_FD_READABLE(pc->fde);
394 }
395 pc->processing = 0;
396 }
397
398 if (!NT_STATUS_IS_OK(status)) {
399 packet_error(pc, status);
400 return;
401 }
402
403 /* Have we consumed the whole buffer yet? */
404 if (pc->partial.length == 0) {
405 return;
406 }
407
408 /* we got multiple packets in one tcp read */
409 if (pc->ev == NULL) {
410 goto next_partial;
411 }
412
413 blob = pc->partial;
414 blob.length = pc->num_read;
415
416 status = pc->full_request(pc->private, blob, &pc->packet_size);
417 if (NT_STATUS_IS_ERR(status)) {
418 packet_error(pc, status);
419 return;
420 }
421
422 if (!NT_STATUS_IS_OK(status)) {
423 return;
424 }
425
426 event_add_timed(pc->ev, pc, timeval_zero(), packet_next_event, pc);
427 }
428
429
430 /*
431 temporarily disable receiving
432 */
packet_recv_disable(struct packet_context * pc)433 _PUBLIC_ void packet_recv_disable(struct packet_context *pc)
434 {
435 EVENT_FD_NOT_READABLE(pc->fde);
436 pc->recv_disable = True;
437 }
438
439 /*
440 re-enable receiving
441 */
packet_recv_enable(struct packet_context * pc)442 _PUBLIC_ void packet_recv_enable(struct packet_context *pc)
443 {
444 EVENT_FD_READABLE(pc->fde);
445 pc->recv_disable = False;
446 if (pc->num_read != 0 && pc->packet_size >= pc->num_read) {
447 event_add_timed(pc->ev, pc, timeval_zero(), packet_next_event, pc);
448 }
449 }
450
451 /*
452 trigger a run of the send queue
453 */
packet_queue_run(struct packet_context * pc)454 _PUBLIC_ void packet_queue_run(struct packet_context *pc)
455 {
456 while (pc->send_queue) {
457 struct send_element *el = pc->send_queue;
458 NTSTATUS status;
459 size_t nwritten;
460 DATA_BLOB blob = data_blob_const(el->blob.data + el->nsent,
461 el->blob.length - el->nsent);
462
463 status = socket_send(pc->sock, &blob, &nwritten);
464
465 if (NT_STATUS_IS_ERR(status)) {
466 packet_error(pc, status);
467 return;
468 }
469 if (!NT_STATUS_IS_OK(status)) {
470 return;
471 }
472 el->nsent += nwritten;
473 if (el->nsent == el->blob.length) {
474 DLIST_REMOVE(pc->send_queue, el);
475 if (el->send_callback) {
476 el->send_callback(el->send_callback_private);
477 }
478 talloc_free(el);
479 }
480 }
481
482 /* we're out of requests to send, so don't wait for write
483 events any more */
484 EVENT_FD_NOT_WRITEABLE(pc->fde);
485 }
486
487 /*
488 put a packet in the send queue. When the packet is actually sent,
489 call send_callback.
490
491 Useful for operations that must occour after sending a message, such
492 as the switch to SASL encryption after as sucessful LDAP bind relpy.
493 */
packet_send_callback(struct packet_context * pc,DATA_BLOB blob,packet_send_callback_fn_t send_callback,void * private)494 _PUBLIC_ NTSTATUS packet_send_callback(struct packet_context *pc, DATA_BLOB blob,
495 packet_send_callback_fn_t send_callback,
496 void *private)
497 {
498 struct send_element *el;
499 el = talloc(pc, struct send_element);
500 NT_STATUS_HAVE_NO_MEMORY(el);
501
502 DLIST_ADD_END(pc->send_queue, el, struct send_element *);
503 el->blob = blob;
504 el->nsent = 0;
505 el->send_callback = send_callback;
506 el->send_callback_private = private;
507
508 /* if we aren't going to free the packet then we must reference it
509 to ensure it doesn't disappear before going out */
510 if (pc->nofree) {
511 if (!talloc_reference(el, blob.data)) {
512 return NT_STATUS_NO_MEMORY;
513 }
514 } else {
515 talloc_steal(el, blob.data);
516 }
517
518 if (private && !talloc_reference(el, private)) {
519 return NT_STATUS_NO_MEMORY;
520 }
521
522 EVENT_FD_WRITEABLE(pc->fde);
523
524 return NT_STATUS_OK;
525 }
526
527 /*
528 put a packet in the send queue
529 */
packet_send(struct packet_context * pc,DATA_BLOB blob)530 _PUBLIC_ NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob)
531 {
532 return packet_send_callback(pc, blob, NULL, NULL);
533 }
534
535
536 /*
537 a full request checker for NBT formatted packets (first 3 bytes are length)
538 */
packet_full_request_nbt(void * private,DATA_BLOB blob,size_t * size)539 _PUBLIC_ NTSTATUS packet_full_request_nbt(void *private, DATA_BLOB blob, size_t *size)
540 {
541 if (blob.length < 4) {
542 return STATUS_MORE_ENTRIES;
543 }
544 *size = 4 + smb_len(blob.data);
545 if (*size > blob.length) {
546 return STATUS_MORE_ENTRIES;
547 }
548 return NT_STATUS_OK;
549 }
550
551
552 /*
553 work out if a packet is complete for protocols that use a 32 bit network byte
554 order length
555 */
packet_full_request_u32(void * private,DATA_BLOB blob,size_t * size)556 _PUBLIC_ NTSTATUS packet_full_request_u32(void *private, DATA_BLOB blob, size_t *size)
557 {
558 if (blob.length < 4) {
559 return STATUS_MORE_ENTRIES;
560 }
561 *size = 4 + RIVAL(blob.data, 0);
562 if (*size > blob.length) {
563 return STATUS_MORE_ENTRIES;
564 }
565 return NT_STATUS_OK;
566 }
567