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