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