r12608: Remove some unused #include lines.
[sfrench/samba-autobuild/.git] / source4 / smb_server / smb / request.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Andrew Tridgell              2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22   this file implements functions for manipulating the 'struct smbsrv_request' structure in smbd
23 */
24
25 #include "includes.h"
26 #include "smb_server/smb_server.h"
27 #include "smbd/service_stream.h"
28 #include "lib/stream/packet.h"
29 #include "ntvfs/ntvfs.h"
30
31
32 /* we over allocate the data buffer to prevent too many realloc calls */
33 #define REQ_OVER_ALLOCATION 0
34
35 /* destroy a request structure */
36 void req_destroy(struct smbsrv_request *req)
37 {
38         /* ahh, its so nice to destroy a complex structure in such a
39          * simple way! */
40         talloc_free(req);
41 }
42
43 /****************************************************************************
44 construct a basic request packet, mostly used to construct async packets
45 such as change notify and oplock break requests
46 ****************************************************************************/
47 struct smbsrv_request *init_smb_request(struct smbsrv_connection *smb_conn)
48 {
49         struct smbsrv_request *req;
50
51         req = talloc(smb_conn, struct smbsrv_request);
52         if (!req) {
53                 return NULL;
54         }
55
56         ZERO_STRUCTP(req);
57
58         /* setup the request context */
59         req->smb_conn = smb_conn;
60
61         req->async_states = talloc(req, struct ntvfs_async_state);
62         if (!req->async_states) {
63                 talloc_free(req);
64                 return NULL;
65         }
66         req->async_states->state = 0;
67
68         return req;
69 }
70
71
72 /*
73   setup a chained reply in req->out with the given word count and initial data buffer size. 
74 */
75 static void req_setup_chain_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen)
76 {
77         uint32_t chain_base_size = req->out.size;
78
79         /* we need room for the wct value, the words, the buffer length and the buffer */
80         req->out.size += 1 + VWV(wct) + 2 + buflen;
81
82         /* over allocate by a small amount */
83         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
84
85         req->out.buffer = talloc_realloc(req, req->out.buffer, 
86                                          uint8_t, req->out.allocated);
87         if (!req->out.buffer) {
88                 smbsrv_terminate_connection(req->smb_conn, "allocation failed");
89                 return;
90         }
91
92         req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
93         req->out.vwv = req->out.buffer + chain_base_size + 1;
94         req->out.wct = wct;
95         req->out.data = req->out.vwv + VWV(wct) + 2;
96         req->out.data_size = buflen;
97         req->out.ptr = req->out.data;
98
99         SCVAL(req->out.buffer, chain_base_size, wct);
100         SSVAL(req->out.vwv, VWV(wct), buflen);
101 }
102
103
104 /*
105   setup a reply in req->out with the given word count and initial data buffer size. 
106   the caller will then fill in the command words and data before calling req_send_reply() to 
107   send the reply on its way
108 */
109 void req_setup_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen)
110 {
111         uint16_t flags2;
112
113         if (req->chain_count != 0) {
114                 req_setup_chain_reply(req, wct, buflen);
115                 return;
116         }
117
118         req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen;
119
120         /* over allocate by a small amount */
121         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
122
123         req->out.buffer = talloc_size(req, req->out.allocated);
124         if (!req->out.buffer) {
125                 smbsrv_terminate_connection(req->smb_conn, "allocation failed");
126                 return;
127         }
128
129         flags2 = FLAGS2_LONG_PATH_COMPONENTS | 
130                 FLAGS2_EXTENDED_ATTRIBUTES | 
131                 FLAGS2_IS_LONG_NAME;
132         flags2 |= (req->flags2 & (FLAGS2_UNICODE_STRINGS|FLAGS2_EXTENDED_SECURITY));
133         if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
134                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
135         }
136
137         req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
138         req->out.vwv = req->out.hdr + HDR_VWV;
139         req->out.wct = wct;
140         req->out.data = req->out.vwv + VWV(wct) + 2;
141         req->out.data_size = buflen;
142         req->out.ptr = req->out.data;
143
144         SIVAL(req->out.hdr, HDR_RCLS, 0);
145
146         SCVAL(req->out.hdr, HDR_WCT, wct);
147         SSVAL(req->out.vwv, VWV(wct), buflen);
148
149         memcpy(req->out.hdr, "\377SMB", 4);
150         SCVAL(req->out.hdr,HDR_FLG, FLAG_REPLY | FLAG_CASELESS_PATHNAMES); 
151         SSVAL(req->out.hdr,HDR_FLG2, flags2);
152         SSVAL(req->out.hdr,HDR_PIDHIGH,0);
153         memset(req->out.hdr + HDR_SS_FIELD, 0, 10);
154
155         if (req->in.hdr) {
156                 /* copy the cmd, tid, pid, uid and mid from the request */
157                 SCVAL(req->out.hdr,HDR_COM,CVAL(req->in.hdr,HDR_COM));  
158                 SSVAL(req->out.hdr,HDR_TID,SVAL(req->in.hdr,HDR_TID));
159                 SSVAL(req->out.hdr,HDR_PID,SVAL(req->in.hdr,HDR_PID));
160                 SSVAL(req->out.hdr,HDR_UID,SVAL(req->in.hdr,HDR_UID));
161                 SSVAL(req->out.hdr,HDR_MID,SVAL(req->in.hdr,HDR_MID));
162         } else {
163                 SSVAL(req->out.hdr,HDR_TID,0);
164                 SSVAL(req->out.hdr,HDR_PID,0);
165                 SSVAL(req->out.hdr,HDR_UID,0);
166                 SSVAL(req->out.hdr,HDR_MID,0);
167         }
168 }
169
170
171 /*
172   setup a copy of a request, used when the server needs to send
173   more than one reply for a single request packet
174 */
175 struct smbsrv_request *req_setup_secondary(struct smbsrv_request *old_req)
176 {
177         struct smbsrv_request *req;
178         ptrdiff_t diff;
179
180         req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));
181         if (req == NULL) {
182                 return NULL;
183         }
184
185         req->out.buffer = talloc_memdup(req, req->out.buffer, req->out.allocated);
186         if (req->out.buffer == NULL) {
187                 talloc_free(req);
188                 return NULL;
189         }
190
191         diff = req->out.buffer - old_req->out.buffer;
192
193         req->out.hdr  += diff;
194         req->out.vwv  += diff;
195         req->out.data += diff;
196         req->out.ptr  += diff;
197
198         return req;
199 }
200
201 /*
202   work out the maximum data size we will allow for this reply, given
203   the negotiated max_xmit. The basic reply packet must be setup before
204   this call
205
206   note that this is deliberately a signed integer reply
207 */
208 int req_max_data(struct smbsrv_request *req)
209 {
210         int ret;
211         ret = req->smb_conn->negotiate.max_send;
212         ret -= PTR_DIFF(req->out.data, req->out.hdr);
213         if (ret < 0) ret = 0;
214         return ret;
215 }
216
217
218 /*
219   grow the allocation of the data buffer portion of a reply
220   packet. Note that as this can reallocate the packet buffer this
221   invalidates any local pointers into the packet.
222
223   To cope with this req->out.ptr is supplied. This will be updated to
224   point at the same offset into the packet as before this call
225 */
226 static void req_grow_allocation(struct smbsrv_request *req, uint_t new_size)
227 {
228         int delta;
229         uint8_t *buf2;
230
231         delta = new_size - req->out.data_size;
232         if (delta + req->out.size <= req->out.allocated) {
233                 /* it fits in the preallocation */
234                 return;
235         }
236
237         /* we need to realloc */
238         req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
239         buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
240         if (buf2 == NULL) {
241                 smb_panic("out of memory in req_grow_allocation");
242         }
243
244         if (buf2 == req->out.buffer) {
245                 /* the malloc library gave us the same pointer */
246                 return;
247         }
248         
249         /* update the pointers into the packet */
250         req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
251         req->out.ptr  = buf2 + PTR_DIFF(req->out.ptr,  req->out.buffer);
252         req->out.vwv  = buf2 + PTR_DIFF(req->out.vwv,  req->out.buffer);
253         req->out.hdr  = buf2 + PTR_DIFF(req->out.hdr,  req->out.buffer);
254
255         req->out.buffer = buf2;
256 }
257
258
259 /*
260   grow the data buffer portion of a reply packet. Note that as this
261   can reallocate the packet buffer this invalidates any local pointers
262   into the packet. 
263
264   To cope with this req->out.ptr is supplied. This will be updated to
265   point at the same offset into the packet as before this call
266 */
267 void req_grow_data(struct smbsrv_request *req, uint_t new_size)
268 {
269         int delta;
270
271         if (!(req->control_flags & REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {
272                 smb_panic("reply buffer too large!");
273         }
274
275         req_grow_allocation(req, new_size);
276
277         delta = new_size - req->out.data_size;
278
279         req->out.size += delta;
280         req->out.data_size += delta;
281
282         /* set the BCC to the new data size */
283         SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
284 }
285
286 /*
287   send a reply and destroy the request buffer
288
289   note that this only looks at req->out.buffer and req->out.size, allowing manually 
290   constructed packets to be sent
291 */
292 void req_send_reply_nosign(struct smbsrv_request *req)
293 {
294         DATA_BLOB blob;
295         NTSTATUS status;
296
297         if (req->out.size > NBT_HDR_SIZE) {
298                 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
299         }
300
301         blob = data_blob_const(req->out.buffer, req->out.size);
302         status = packet_send(req->smb_conn->packet, blob);
303         if (!NT_STATUS_IS_OK(status)) {
304                 smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
305         }
306         req_destroy(req);
307 }
308
309 /*
310   possibly sign a message then send a reply and destroy the request buffer
311
312   note that this only looks at req->out.buffer and req->out.size, allowing manually 
313   constructed packets to be sent
314 */
315 void req_send_reply(struct smbsrv_request *req)
316 {
317         req_sign_packet(req);
318
319         req_send_reply_nosign(req);
320 }
321
322
323
324 /* 
325    construct and send an error packet with a forced DOS error code
326    this is needed to match win2000 behaviour for some parts of the protocol
327 */
328 void req_reply_dos_error(struct smbsrv_request *req, uint8_t eclass, uint16_t ecode)
329 {
330         /* if the basic packet hasn't been setup yet then do it now */
331         if (req->out.buffer == NULL) {
332                 req_setup_reply(req, 0, 0);
333         }
334
335         SCVAL(req->out.hdr, HDR_RCLS, eclass);
336         SSVAL(req->out.hdr, HDR_ERR, ecode);
337         SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);       
338         req_send_reply(req);
339 }
340
341 /* 
342    setup the header of a reply to include an NTSTATUS code
343 */
344 void req_setup_error(struct smbsrv_request *req, NTSTATUS status)
345 {
346         if (!req->smb_conn->config.nt_status_support || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) {
347                 /* convert to DOS error codes */
348                 uint8_t eclass;
349                 uint32_t ecode;
350                 ntstatus_to_dos(status, &eclass, &ecode);
351                 SCVAL(req->out.hdr, HDR_RCLS, eclass);
352                 SSVAL(req->out.hdr, HDR_ERR, ecode);
353                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
354                 return;
355         }
356
357         if (NT_STATUS_IS_DOS(status)) {
358                 /* its a encoded DOS error, using the reserved range */
359                 SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status));
360                 SSVAL(req->out.hdr, HDR_ERR,  NT_STATUS_DOS_CODE(status));
361                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
362         } else {
363                 SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));
364                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);
365         }
366 }
367
368 /* 
369    construct and send an error packet, then destroy the request 
370    auto-converts to DOS error format when appropriate
371 */
372 void req_reply_error(struct smbsrv_request *req, NTSTATUS status)
373 {
374         if (req->smb_conn->connection->event.fde == NULL) {
375                 /* the socket has been destroyed - no point trying to send an error! */
376                 talloc_free(req);
377                 return;
378         }
379         req_setup_reply(req, 0, 0);
380
381         /* error returns never have any data */
382         req_grow_data(req, 0);
383
384         req_setup_error(req, status);
385         req_send_reply(req);
386 }
387
388
389 /*
390   push a string into the data portion of the request packet, growing it if necessary
391   this gets quite tricky - please be very careful to cover all cases when modifying this
392
393   if dest is NULL, then put the string at the end of the data portion of the packet
394
395   if dest_len is -1 then no limit applies
396 */
397 size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, uint_t flags)
398 {
399         size_t len;
400         uint_t grow_size;
401         uint8_t *buf0;
402         const int max_bytes_per_char = 3;
403
404         if (!(flags & (STR_ASCII|STR_UNICODE))) {
405                 flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
406         }
407
408         if (dest == NULL) {
409                 dest = req->out.data + req->out.data_size;
410         }
411
412         if (dest_len != -1) {
413                 len = dest_len;
414         } else {
415                 len = (strlen(str)+2) * max_bytes_per_char;
416         }
417
418         grow_size = len + PTR_DIFF(dest, req->out.data);
419         buf0 = req->out.buffer;
420
421         req_grow_allocation(req, grow_size);
422
423         if (buf0 != req->out.buffer) {
424                 dest = req->out.buffer + PTR_DIFF(dest, buf0);
425         }
426
427         len = push_string(dest, str, len, flags);
428
429         grow_size = len + PTR_DIFF(dest, req->out.data);
430
431         if (grow_size > req->out.data_size) {
432                 req_grow_data(req, grow_size);
433         }
434
435         return len;
436 }
437
438 /*
439   append raw bytes into the data portion of the request packet
440   return the number of bytes added
441 */
442 size_t req_append_bytes(struct smbsrv_request *req, 
443                         const uint8_t *bytes, size_t byte_len)
444 {
445         req_grow_allocation(req, byte_len + req->out.data_size);
446         memcpy(req->out.data + req->out.data_size, bytes, byte_len);
447         req_grow_data(req, byte_len + req->out.data_size);
448         return byte_len;
449 }
450 /*
451   append variable block (type 5 buffer) into the data portion of the request packet
452   return the number of bytes added
453 */
454 size_t req_append_var_block(struct smbsrv_request *req, 
455                 const uint8_t *bytes, uint16_t byte_len)
456 {
457         req_grow_allocation(req, byte_len + 3 + req->out.data_size);
458         SCVAL(req->out.data + req->out.data_size, 0, 5);
459         SSVAL(req->out.data + req->out.data_size, 1, byte_len);         /* add field length */
460         if (byte_len > 0) {
461                 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
462         }
463         req_grow_data(req, byte_len + 3 + req->out.data_size);
464         return byte_len + 3;
465 }
466 /*
467   pull a UCS2 string from a request packet, returning a talloced unix string
468
469   the string length is limited by the 3 things:
470    - the data size in the request (end of packet)
471    - the passed 'byte_len' if it is not -1
472    - the end of string (null termination)
473
474   Note that 'byte_len' is the number of bytes in the packet
475
476   on failure zero is returned and *dest is set to NULL, otherwise the number
477   of bytes consumed in the packet is returned
478 */
479 static size_t req_pull_ucs2(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
480 {
481         int src_len, src_len2, alignment=0;
482         ssize_t ret;
483         char *dest2;
484
485         if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
486                 src++;
487                 alignment=1;
488                 if (byte_len != -1) {
489                         byte_len--;
490                 }
491         }
492
493         if (flags & STR_NO_RANGE_CHECK) {
494                 src_len = byte_len;
495         } else {
496                 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
497                 if (byte_len != -1 && src_len > byte_len) {
498                         src_len = byte_len;
499                 }
500         }
501
502         if (src_len < 0) {
503                 *dest = NULL;
504                 return 0;
505         }
506         
507         src_len2 = utf16_len_n(src, src_len);
508         if (src_len2 == 0) {
509                 *dest = talloc_strdup(req, "");
510                 return src_len2 + alignment;
511         }
512
513         ret = convert_string_talloc(req, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
514
515         if (ret == -1) {
516                 *dest = NULL;
517                 return 0;
518         }
519         *dest = dest2;
520
521         return src_len2 + alignment;
522 }
523
524 /*
525   pull a ascii string from a request packet, returning a talloced string
526
527   the string length is limited by the 3 things:
528    - the data size in the request (end of packet)
529    - the passed 'byte_len' if it is not -1
530    - the end of string (null termination)
531
532   Note that 'byte_len' is the number of bytes in the packet
533
534   on failure zero is returned and *dest is set to NULL, otherwise the number
535   of bytes consumed in the packet is returned
536 */
537 static size_t req_pull_ascii(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
538 {
539         int src_len, src_len2;
540         ssize_t ret;
541         char *dest2;
542
543         if (flags & STR_NO_RANGE_CHECK) {
544                 src_len = byte_len;
545         } else {
546                 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
547                 if (src_len < 0) {
548                         *dest = NULL;
549                         return 0;
550                 }
551                 if (byte_len != -1 && src_len > byte_len) {
552                         src_len = byte_len;
553                 }
554         }
555
556         src_len2 = strnlen((const char *)src, src_len);
557         if (src_len2 <= src_len - 1) {
558                 /* include the termination if we didn't reach the end of the packet */
559                 src_len2++;
560         }
561
562         ret = convert_string_talloc(req, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
563
564         if (ret == -1) {
565                 *dest = NULL;
566                 return 0;
567         }
568         *dest = dest2;
569
570         return src_len2;
571 }
572
573 /*
574   pull a string from a request packet, returning a talloced string
575
576   the string length is limited by the 3 things:
577    - the data size in the request (end of packet)
578    - the passed 'byte_len' if it is not -1
579    - the end of string (null termination)
580
581   Note that 'byte_len' is the number of bytes in the packet
582
583   on failure zero is returned and *dest is set to NULL, otherwise the number
584   of bytes consumed in the packet is returned
585 */
586 size_t req_pull_string(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
587 {
588         if (!(flags & STR_ASCII) && 
589             (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
590                 return req_pull_ucs2(req, dest, src, byte_len, flags);
591         }
592
593         return req_pull_ascii(req, dest, src, byte_len, flags);
594 }
595
596
597 /*
598   pull a ASCII4 string buffer from a request packet, returning a talloced string
599   
600   an ASCII4 buffer is a null terminated string that has a prefix
601   of the character 0x4. It tends to be used in older parts of the protocol.
602
603   on failure *dest is set to the zero length string. This seems to
604   match win2000 behaviour
605 */
606 size_t req_pull_ascii4(struct smbsrv_request *req, const char **dest, const uint8_t *src, uint_t flags)
607 {
608         ssize_t ret;
609
610         if (PTR_DIFF(src, req->in.data) + 1 > req->in.data_size) {
611                 /* win2000 treats this as the NULL string! */
612                 (*dest) = talloc_strdup(req, "");
613                 return 0;
614         }
615
616         /* this consumes the 0x4 byte. We don't check whether the byte
617            is actually 0x4 or not. This matches win2000 server
618            behaviour */
619         src++;
620
621         ret = req_pull_string(req, dest, src, -1, flags);
622         if (ret == -1) {
623                 (*dest) = talloc_strdup(req, "");
624                 return 1;
625         }
626         
627         return ret + 1;
628 }
629
630 /*
631   pull a DATA_BLOB from a request packet, returning a talloced blob
632
633   return False if any part is outside the data portion of the packet
634 */
635 BOOL req_pull_blob(struct smbsrv_request *req, const uint8_t *src, int len, DATA_BLOB *blob)
636 {
637         if (len != 0 && req_data_oob(req, src, len)) {
638                 return False;
639         }
640
641         (*blob) = data_blob_talloc(req, src, len);
642
643         return True;
644 }
645
646 /* check that a lump of data in a request is within the bounds of the data section of
647    the packet */
648 BOOL req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count)
649 {
650         if (count == 0) {
651                 return False;
652         }
653         
654         /* be careful with wraparound! */
655         if (ptr < req->in.data ||
656             ptr >= req->in.data + req->in.data_size ||
657             count > req->in.data_size ||
658             ptr + count > req->in.data + req->in.data_size) {
659                 return True;
660         }
661         return False;
662 }
663
664
665 /* 
666    pull an open file handle from a packet, taking account of the chained_fnum
667 */
668 uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
669 {
670         if (req->chained_fnum != -1) {
671                 return req->chained_fnum;
672         }
673         return SVAL(base, offset);
674 }