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