bd33e8cfc76cea7f36a5f516980674359b34a26c
[jelmer/samba4-debian.git] / source / 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         smb_conn->pkt_count++;
51
52         req = talloc_p(smb_conn, struct smbsrv_request);
53         if (!req) {
54                 return NULL;
55         }
56
57         ZERO_STRUCTP(req);
58
59         /* setup the request context */
60         req->smb_conn = smb_conn;
61
62         req->async_states = talloc_p(req, struct ntvfs_async_state);
63         if (!req->async_states) {
64                 talloc_free(req);
65                 return NULL;
66         }
67         req->async_states->state = 0;
68
69         return req;
70 }
71
72
73 /*
74   setup a chained reply in req->out with the given word count and initial data buffer size. 
75 */
76 static void req_setup_chain_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen)
77 {
78         uint32_t chain_base_size = req->out.size;
79
80         /* we need room for the wct value, the words, the buffer length and the buffer */
81         req->out.size += 1 + VWV(wct) + 2 + buflen;
82
83         /* over allocate by a small amount */
84         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
85
86         req->out.buffer = talloc_realloc(req, req->out.buffer, 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, 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         if (req->out.size > NBT_HDR_SIZE) {
295                 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
296         }
297
298         /* add the request to the list of requests that need to be
299            sent to the client, then mark the socket event structure
300            ready for write events */
301         DLIST_ADD_END(req->smb_conn->pending_send, req, struct smbsrv_request *);
302
303         req->smb_conn->connection->event.fde->flags |= EVENT_FD_WRITE;
304 }
305
306 /*
307   possibly sign a message then send a reply and destroy the request buffer
308
309   note that this only looks at req->out.buffer and req->out.size, allowing manually 
310   constructed packets to be sent
311 */
312 void req_send_reply(struct smbsrv_request *req)
313 {
314         req_sign_packet(req);
315
316         req_send_reply_nosign(req);
317 }
318
319
320
321 /* 
322    construct and send an error packet with a forced DOS error code
323    this is needed to match win2000 behaviour for some parts of the protocol
324 */
325 void req_reply_dos_error(struct smbsrv_request *req, uint8_t eclass, uint16_t ecode)
326 {
327         /* if the basic packet hasn't been setup yet then do it now */
328         if (req->out.buffer == NULL) {
329                 req_setup_reply(req, 0, 0);
330         }
331
332         SCVAL(req->out.hdr, HDR_RCLS, eclass);
333         SSVAL(req->out.hdr, HDR_ERR, ecode);
334         SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);       
335         req_send_reply(req);
336 }
337
338 /* 
339    setup the header of a reply to include an NTSTATUS code
340 */
341 void req_setup_error(struct smbsrv_request *req, NTSTATUS status)
342 {
343         if (!lp_nt_status_support() || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) {
344                 /* convert to DOS error codes */
345                 uint8_t eclass;
346                 uint32_t ecode;
347                 ntstatus_to_dos(status, &eclass, &ecode);
348                 SCVAL(req->out.hdr, HDR_RCLS, eclass);
349                 SSVAL(req->out.hdr, HDR_ERR, ecode);
350                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
351                 return;
352         }
353
354         if (NT_STATUS_IS_DOS(status)) {
355                 /* its a encoded DOS error, using the reserved range */
356                 SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status));
357                 SSVAL(req->out.hdr, HDR_ERR,  NT_STATUS_DOS_CODE(status));
358                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
359         } else {
360                 SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));
361                 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);
362         }
363 }
364
365 /* 
366    construct and send an error packet, then destroy the request 
367    auto-converts to DOS error format when appropriate
368 */
369 void req_reply_error(struct smbsrv_request *req, NTSTATUS status)
370 {
371         req_setup_reply(req, 0, 0);
372
373         /* error returns never have any data */
374         req_grow_data(req, 0);
375
376         req_setup_error(req, status);
377         req_send_reply(req);
378 }
379
380
381 /*
382   push a string into the data portion of the request packet, growing it if necessary
383   this gets quite tricky - please be very careful to cover all cases when modifying this
384
385   if dest is NULL, then put the string at the end of the data portion of the packet
386
387   if dest_len is -1 then no limit applies
388 */
389 size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, uint_t flags)
390 {
391         size_t len;
392         uint_t grow_size;
393         uint8_t *buf0;
394         const int max_bytes_per_char = 3;
395
396         if (!(flags & (STR_ASCII|STR_UNICODE))) {
397                 flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
398         }
399
400         if (dest == NULL) {
401                 dest = req->out.data + req->out.data_size;
402         }
403
404         if (dest_len != -1) {
405                 len = dest_len;
406         } else {
407                 len = (strlen(str)+2) * max_bytes_per_char;
408         }
409
410         grow_size = len + PTR_DIFF(dest, req->out.data);
411         buf0 = req->out.buffer;
412
413         req_grow_allocation(req, grow_size);
414
415         if (buf0 != req->out.buffer) {
416                 dest = req->out.buffer + PTR_DIFF(dest, buf0);
417         }
418
419         len = push_string(dest, str, len, flags);
420
421         grow_size = len + PTR_DIFF(dest, req->out.data);
422
423         if (grow_size > req->out.data_size) {
424                 req_grow_data(req, grow_size);
425         }
426
427         return len;
428 }
429
430 /*
431   append raw bytes into the data portion of the request packet
432   return the number of bytes added
433 */
434 size_t req_append_bytes(struct smbsrv_request *req, 
435                         const uint8_t *bytes, size_t byte_len)
436 {
437         req_grow_allocation(req, byte_len + req->out.data_size);
438         memcpy(req->out.data + req->out.data_size, bytes, byte_len);
439         req_grow_data(req, byte_len + req->out.data_size);
440         return byte_len;
441 }
442 /*
443   append variable block (type 5 buffer) into the data portion of the request packet
444   return the number of bytes added
445 */
446 size_t req_append_var_block(struct smbsrv_request *req, 
447                 const uint8_t *bytes, uint16_t byte_len)
448 {
449         req_grow_allocation(req, byte_len + 3 + req->out.data_size);
450         SCVAL(req->out.data + req->out.data_size, 0, 5);
451         SSVAL(req->out.data + req->out.data_size, 1, byte_len);         /* add field length */
452         if (byte_len > 0) {
453                 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
454         }
455         req_grow_data(req, byte_len + 3 + req->out.data_size);
456         return byte_len + 3;
457 }
458 /*
459   pull a UCS2 string from a request packet, returning a talloced unix string
460
461   the string length is limited by the 3 things:
462    - the data size in the request (end of packet)
463    - the passed 'byte_len' if it is not -1
464    - the end of string (null termination)
465
466   Note that 'byte_len' is the number of bytes in the packet
467
468   on failure zero is returned and *dest is set to NULL, otherwise the number
469   of bytes consumed in the packet is returned
470 */
471 static size_t req_pull_ucs2(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
472 {
473         int src_len, src_len2, alignment=0;
474         ssize_t ret;
475         char *dest2;
476
477         if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
478                 src++;
479                 alignment=1;
480                 if (byte_len != -1) {
481                         byte_len--;
482                 }
483         }
484
485         if (flags & STR_NO_RANGE_CHECK) {
486                 src_len = byte_len;
487         } else {
488                 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
489                 if (src_len < 0) {
490                         *dest = NULL;
491                         return 0;
492                 }
493
494                 if (byte_len != -1 && src_len > byte_len) {
495                         src_len = byte_len;
496                 }
497         }
498
499         src_len2 = utf16_len_n(src, src_len);
500         if (src_len2 == 0) {
501                 *dest = talloc_strdup(req, "");
502                 return src_len2 + alignment;
503         }
504
505         ret = convert_string_talloc(req, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
506
507         if (ret == -1) {
508                 *dest = NULL;
509                 return 0;
510         }
511         *dest = dest2;
512
513         return src_len2 + alignment;
514 }
515
516 /*
517   pull a ascii string from a request packet, returning a talloced string
518
519   the string length is limited by the 3 things:
520    - the data size in the request (end of packet)
521    - the passed 'byte_len' if it is not -1
522    - the end of string (null termination)
523
524   Note that 'byte_len' is the number of bytes in the packet
525
526   on failure zero is returned and *dest is set to NULL, otherwise the number
527   of bytes consumed in the packet is returned
528 */
529 static size_t req_pull_ascii(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
530 {
531         int src_len, src_len2;
532         ssize_t ret;
533         char *dest2;
534
535         if (flags & STR_NO_RANGE_CHECK) {
536                 src_len = byte_len;
537         } else {
538                 src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
539                 if (src_len < 0) {
540                         *dest = NULL;
541                         return 0;
542                 }
543                 if (byte_len != -1 && src_len > byte_len) {
544                         src_len = byte_len;
545                 }
546         }
547
548         src_len2 = strnlen((const char *)src, src_len);
549         if (src_len2 <= src_len - 1) {
550                 /* include the termination if we didn't reach the end of the packet */
551                 src_len2++;
552         }
553
554         ret = convert_string_talloc(req, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
555
556         if (ret == -1) {
557                 *dest = NULL;
558                 return 0;
559         }
560         *dest = dest2;
561
562         return src_len2;
563 }
564
565 /*
566   pull a string from a request packet, returning a talloced string
567
568   the string length is limited by the 3 things:
569    - the data size in the request (end of packet)
570    - the passed 'byte_len' if it is not -1
571    - the end of string (null termination)
572
573   Note that 'byte_len' is the number of bytes in the packet
574
575   on failure zero is returned and *dest is set to NULL, otherwise the number
576   of bytes consumed in the packet is returned
577 */
578 size_t req_pull_string(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
579 {
580         if (!(flags & STR_ASCII) && 
581             (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
582                 return req_pull_ucs2(req, dest, src, byte_len, flags);
583         }
584
585         return req_pull_ascii(req, dest, src, byte_len, flags);
586 }
587
588
589 /*
590   pull a ASCII4 string buffer from a request packet, returning a talloced string
591   
592   an ASCII4 buffer is a null terminated string that has a prefix
593   of the character 0x4. It tends to be used in older parts of the protocol.
594
595   on failure *dest is set to the zero length string. This seems to
596   match win2000 behaviour
597 */
598 size_t req_pull_ascii4(struct smbsrv_request *req, const char **dest, const uint8_t *src, uint_t flags)
599 {
600         ssize_t ret;
601
602         if (PTR_DIFF(src, req->in.data) + 1 > req->in.data_size) {
603                 /* win2000 treats this as the NULL string! */
604                 (*dest) = talloc_strdup(req, "");
605                 return 0;
606         }
607
608         /* this consumes the 0x4 byte. We don't check whether the byte
609            is actually 0x4 or not. This matches win2000 server
610            behaviour */
611         src++;
612
613         ret = req_pull_string(req, dest, src, -1, flags);
614         if (ret == -1) {
615                 (*dest) = talloc_strdup(req, "");
616                 return 1;
617         }
618         
619         return ret + 1;
620 }
621
622 /*
623   pull a DATA_BLOB from a request packet, returning a talloced blob
624
625   return False if any part is outside the data portion of the packet
626 */
627 BOOL req_pull_blob(struct smbsrv_request *req, const uint8_t *src, int len, DATA_BLOB *blob)
628 {
629         if (len != 0 && req_data_oob(req, src, len)) {
630                 return False;
631         }
632
633         (*blob) = data_blob_talloc(req, src, len);
634
635         return True;
636 }
637
638 /* check that a lump of data in a request is within the bounds of the data section of
639    the packet */
640 BOOL req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count)
641 {
642         if (count == 0) {
643                 return False;
644         }
645         
646         /* be careful with wraparound! */
647         if (ptr < req->in.data ||
648             ptr >= req->in.data + req->in.data_size ||
649             count > req->in.data_size ||
650             ptr + count > req->in.data + req->in.data_size) {
651                 return True;
652         }
653         return False;
654 }
655
656
657 /* 
658    pull an open file handle from a packet, taking account of the chained_fnum
659 */
660 uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
661 {
662         if (req->chained_fnum != -1) {
663                 return req->chained_fnum;
664         }
665         return SVAL(base, offset);
666 }