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