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