move to SAFE_FREE()
[jra/samba/.git] / source / rpc_parse / parse_prs.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba memory buffer functions
5    Copyright (C) Andrew Tridgell              1992-1997
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
7    Copyright (C) Jeremy Allison 1999.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 extern int DEBUGLEVEL;
25
26 #include "includes.h"
27
28
29 /*******************************************************************
30 dump a prs to a file
31  ********************************************************************/
32 void prs_dump(char *name, int v, prs_struct *ps)
33 {
34         int fd, i;
35         pstring fname;
36         if (DEBUGLEVEL < 50) return;
37         for (i=1;i<100;i++) {
38                 if (v != -1) {
39                         slprintf(fname,sizeof(fname)-1, "/tmp/%s_%d.%d.prs", name, v, i);
40                 } else {
41                         slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.prs", name, i);
42                 }
43                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
44                 if (fd != -1 || errno != EEXIST) break;
45         }
46         if (fd != -1) {
47                 write(fd, ps->data_p + ps->data_offset, ps->buffer_size - ps->data_offset);
48                 close(fd);
49                 DEBUG(0,("created %s\n", fname));
50         }
51 }
52
53
54
55 /*******************************************************************
56  debug output for parsing info.
57
58  XXXX side-effect of this function is to increase the debug depth XXXX
59
60  ********************************************************************/
61 void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
62 {
63         DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));
64 }
65
66
67 /*******************************************************************
68  Initialise a parse structure - malloc the data if requested.
69  ********************************************************************/
70 BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io)
71 {
72         ZERO_STRUCTP(ps);
73         ps->io = io;
74         ps->bigendian_data = RPC_LITTLE_ENDIAN;
75         ps->align = RPC_PARSE_ALIGN;
76         ps->is_dynamic = False;
77         ps->data_offset = 0;
78         ps->buffer_size = 0;
79         ps->data_p = NULL;
80         ps->mem_ctx = ctx;
81
82         if (size != 0) {
83                 ps->buffer_size = size;
84                 if((ps->data_p = (char *)malloc((size_t)size)) == NULL) {
85                         DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size));
86                         return False;
87                 }
88                 ps->is_dynamic = True; /* We own this memory. */
89         }
90
91         return True;
92 }
93
94 /*******************************************************************
95  read from a socket into memory.
96  ********************************************************************/
97 BOOL prs_read(prs_struct *ps, int fd, size_t len, int timeout)
98 {
99         BOOL ok;
100         size_t prev_size = ps->buffer_size;
101         if (!prs_grow(ps, len))
102                 return False;
103
104         if (timeout > 0) {
105                 ok = (read_with_timeout(fd, &ps->data_p[prev_size],
106                                             len, len,timeout) == len);
107         } else {
108                 ok = (read_data(fd, &ps->data_p[prev_size], len) == len);
109         }
110         return ok;
111 }
112
113 /*******************************************************************
114  Delete the memory in a parse structure - if we own it.
115  ********************************************************************/
116
117 void prs_mem_free(prs_struct *ps)
118 {
119         if(ps->is_dynamic)
120                 SAFE_FREE(ps->data_p);
121         ps->is_dynamic = False;
122         ps->buffer_size = 0;
123         ps->data_offset = 0;
124 }
125
126 /*******************************************************************
127  Allocate memory when unmarshalling... Always zero clears.
128  ********************************************************************/
129
130 char *prs_alloc_mem(prs_struct *ps, size_t size)
131 {
132         char *ret = talloc(ps->mem_ctx, size);
133
134         if (ret)
135                 memset(ret, '\0', size);
136
137         return ret;
138 }
139
140 /*******************************************************************
141  Return the current talloc context we're using.
142  ********************************************************************/
143
144 TALLOC_CTX *prs_get_mem_context(prs_struct *ps)
145 {
146         return ps->mem_ctx;
147 }
148
149 /*******************************************************************
150  Hand some already allocated memory to a prs_struct.
151  ********************************************************************/
152
153 void prs_give_memory(prs_struct *ps, char *buf, uint32 size, BOOL is_dynamic)
154 {
155         ps->is_dynamic = is_dynamic;
156         ps->data_p = buf;
157         ps->buffer_size = size;
158 }
159
160 /*******************************************************************
161  Take some memory back from a prs_struct.
162  ********************************************************************/
163
164 char *prs_take_memory(prs_struct *ps, uint32 *psize)
165 {
166         char *ret = ps->data_p;
167         if(psize)
168                 *psize = ps->buffer_size;
169         ps->is_dynamic = False;
170         prs_mem_free(ps);
171         return ret;
172 }
173
174 /*******************************************************************
175  Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary.
176  ********************************************************************/
177
178 BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize)
179 {
180         if (newsize > ps->buffer_size)
181                 return prs_force_grow(ps, newsize - ps->buffer_size);
182
183         if (newsize < ps->buffer_size) {
184                 char *new_data_p = Realloc(ps->data_p, newsize);
185                 /* if newsize is zero, Realloc acts like free() & returns NULL*/
186                 if (new_data_p == NULL && newsize != 0) {
187                         DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
188                                 (unsigned int)newsize));
189                         DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));
190                         return False;
191                 }
192                 ps->data_p = new_data_p;
193                 ps->buffer_size = newsize;
194         }
195
196         return True;
197 }
198
199 /*******************************************************************
200  Attempt, if needed, to grow a data buffer.
201  Also depends on the data stream mode (io).
202  ********************************************************************/
203
204 BOOL prs_grow(prs_struct *ps, uint32 extra_space)
205 {
206         uint32 new_size;
207         char *new_data;
208
209         ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
210
211         if(ps->data_offset + extra_space <= ps->buffer_size)
212                 return True;
213
214         /*
215          * We cannot grow the buffer if we're not reading
216          * into the prs_struct, or if we don't own the memory.
217          */
218
219         if(UNMARSHALLING(ps) || !ps->is_dynamic) {
220                 DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
221                                 (unsigned int)extra_space));
222                 return False;
223         }
224         
225         /*
226          * Decide how much extra space we really need.
227          */
228
229         extra_space -= (ps->buffer_size - ps->data_offset);
230         if(ps->buffer_size == 0) {
231                 /*
232                  * Ensure we have at least a PDU's length, or extra_space, whichever
233                  * is greater.
234                  */
235
236                 new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
237
238                 if((new_data = malloc(new_size)) == NULL) {
239                         DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
240                         return False;
241                 }
242                 memset(new_data, '\0', new_size );
243         } else {
244                 /*
245                  * If the current buffer size is bigger than the space needed, just 
246                  * double it, else add extra_space.
247                  */
248                 new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);               
249
250                 if ((new_data = Realloc(ps->data_p, new_size)) == NULL) {
251                         DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
252                                 (unsigned int)new_size));
253                         return False;
254                 }
255
256                 memset(&new_data[ps->buffer_size], '\0', new_size - ps->buffer_size);
257         }
258         ps->buffer_size = new_size;
259         ps->data_p = new_data;
260
261         return True;
262 }
263
264 /*******************************************************************
265  Attempt to force a data buffer to grow by len bytes.
266  This is only used when appending more data onto a prs_struct
267  when reading an rpc reply, before unmarshalling it.
268  ********************************************************************/
269
270 BOOL prs_force_grow(prs_struct *ps, uint32 extra_space)
271 {
272         uint32 new_size = ps->buffer_size + extra_space;
273         char *new_data;
274
275         if(!UNMARSHALLING(ps) || !ps->is_dynamic) {
276                 DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
277                                 (unsigned int)extra_space));
278                 return False;
279         }
280
281         if((new_data = Realloc(ps->data_p, new_size)) == NULL) {
282                 DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",
283                         (unsigned int)new_size));
284                 return False;
285         }
286
287         memset(&new_data[ps->buffer_size], '\0', new_size - ps->buffer_size);
288
289         ps->buffer_size = new_size;
290         ps->data_p = new_data;
291
292         return True;
293 }
294
295 /*******************************************************************
296  Get the data pointer (external interface).
297  ********************************************************************/
298
299 char *prs_data_p(prs_struct *ps)
300 {
301         return ps->data_p;
302 }
303
304 /*******************************************************************
305  Get the current data size (external interface).
306  ********************************************************************/
307
308 uint32 prs_data_size(prs_struct *ps)
309 {
310         return ps->buffer_size;
311 }
312
313 /*******************************************************************
314  Fetch the current offset (external interface).
315  ********************************************************************/
316
317 uint32 prs_offset(prs_struct *ps)
318 {
319         return ps->data_offset;
320 }
321
322 /*******************************************************************
323  Set the current offset (external interface).
324  ********************************************************************/
325
326 BOOL prs_set_offset(prs_struct *ps, uint32 offset)
327 {
328         if(offset <= ps->data_offset) {
329                 ps->data_offset = offset;
330                 return True;
331         }
332
333         if(!prs_grow(ps, offset - ps->data_offset))
334                 return False;
335
336         ps->data_offset = offset;
337         return True;
338 }
339
340 /*******************************************************************
341  Append the data from one parse_struct into another.
342  ********************************************************************/
343
344 BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src)
345 {
346         if(!prs_grow(dst, prs_offset(src)))
347                 return False;
348
349         memcpy(&dst->data_p[dst->data_offset], prs_data_p(src), (size_t)prs_offset(src));
350         dst->data_offset += prs_offset(src);
351
352         return True;
353 }
354
355 /*******************************************************************
356  Append some data from one parse_struct into another.
357  ********************************************************************/
358
359 BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len)
360 {       
361         if (len == 0)
362                 return True;
363
364         if(!prs_grow(dst, len))
365                 return False;
366         
367         memcpy(&dst->data_p[dst->data_offset], prs_data_p(src)+start, (size_t)len);
368         dst->data_offset += len;
369
370         return True;
371 }
372
373 /*******************************************************************
374  Append the data from a buffer into a parse_struct.
375  ********************************************************************/
376
377 BOOL prs_append_data(prs_struct *dst, char *src, uint32 len)
378 {
379         if(!prs_grow(dst, len))
380                 return False;
381
382         memcpy(&dst->data_p[dst->data_offset], src, (size_t)len);
383         dst->data_offset += len;
384
385         return True;
386 }
387
388 /*******************************************************************
389  Set the data as X-endian (external interface).
390  ********************************************************************/
391
392 void prs_set_endian_data(prs_struct *ps, BOOL endian)
393 {
394         ps->bigendian_data = endian;
395 }
396
397 /*******************************************************************
398  Align a the data_len to a multiple of align bytes - filling with
399  zeros.
400  ********************************************************************/
401
402 BOOL prs_align(prs_struct *ps)
403 {
404         uint32 mod = ps->data_offset & (ps->align-1);
405
406         if (ps->align != 0 && mod != 0) {
407                 uint32 extra_space = (ps->align - mod);
408                 if(!prs_grow(ps, extra_space))
409                         return False;
410                 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
411                 ps->data_offset += extra_space;
412         }
413
414         return True;
415 }
416
417 /*******************************************************************
418  Align only if required (for the unistr2 string mainly)
419  ********************************************************************/
420
421 BOOL prs_align_needed(prs_struct *ps, uint32 needed)
422 {
423         if (needed==0)
424                 return True;
425         else
426                 return prs_align(ps);
427 }
428
429 /*******************************************************************
430  Ensure we can read/write to a given offset.
431  ********************************************************************/
432
433 char *prs_mem_get(prs_struct *ps, uint32 extra_size)
434 {
435         if(UNMARSHALLING(ps)) {
436                 /*
437                  * If reading, ensure that we can read the requested size item.
438                  */
439                 if (ps->data_offset + extra_size > ps->buffer_size) {
440                         DEBUG(0,("prs_mem_get: reading data of size %u would overrun buffer.\n",
441                                         (unsigned int)extra_size ));
442                         return NULL;
443                 }
444         } else {
445                 /*
446                  * Writing - grow the buffer if needed.
447                  */
448                 if(!prs_grow(ps, extra_size))
449                         return NULL;
450         }
451         return &ps->data_p[ps->data_offset];
452 }
453
454 /*******************************************************************
455  Change the struct type.
456  ********************************************************************/
457
458 void prs_switch_type(prs_struct *ps, BOOL io)
459 {
460         if ((ps->io ^ io) == True)
461                 ps->io=io;
462 }
463
464 /*******************************************************************
465  Force a prs_struct to be dynamic even when it's size is 0.
466  ********************************************************************/
467
468 void prs_force_dynamic(prs_struct *ps)
469 {
470         ps->is_dynamic=True;
471 }
472
473 /*******************************************************************
474  Stream a uint8.
475  ********************************************************************/
476
477 BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
478 {
479         char *q = prs_mem_get(ps, 1);
480         if (q == NULL)
481                 return False;
482
483     if (UNMARSHALLING(ps))
484                 *data8 = CVAL(q,0);
485         else
486                 SCVAL(q,0,*data8);
487
488     DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8));
489
490         ps->data_offset += 1;
491
492         return True;
493 }
494
495 /*******************************************************************
496  Stream a uint16.
497  ********************************************************************/
498
499 BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
500 {
501         char *q = prs_mem_get(ps, sizeof(uint16));
502         if (q == NULL)
503                 return False;
504
505     if (UNMARSHALLING(ps)) {
506                 if (ps->bigendian_data)
507                         *data16 = RSVAL(q,0);
508                 else
509                         *data16 = SVAL(q,0);
510     } else {
511                 if (ps->bigendian_data)
512                         RSSVAL(q,0,*data16);
513                 else
514                         SSVAL(q,0,*data16);
515         }
516
517         DEBUG(5,("%s%04x %s: %04x\n", tab_depth(depth), ps->data_offset, name, *data16));
518
519         ps->data_offset += sizeof(uint16);
520
521         return True;
522 }
523
524 /*******************************************************************
525  Stream a uint32.
526  ********************************************************************/
527
528 BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
529 {
530         char *q = prs_mem_get(ps, sizeof(uint32));
531         if (q == NULL)
532                 return False;
533
534         if (UNMARSHALLING(ps)) {
535                 if (ps->bigendian_data)
536                         *data32 = RIVAL(q,0);
537                 else
538                         *data32 = IVAL(q,0);
539         } else {
540                 if (ps->bigendian_data)
541                         RSIVAL(q,0,*data32);
542                 else
543                         SIVAL(q,0,*data32);
544         }
545
546         DEBUG(5,("%s%04x %s: %08x\n", tab_depth(depth), ps->data_offset, name, *data32));
547
548         ps->data_offset += sizeof(uint32);
549
550         return True;
551 }
552
553 /*******************************************************************
554  Stream a NTSTATUS
555  ********************************************************************/
556
557 BOOL prs_ntstatus(char *name, prs_struct *ps, int depth, NTSTATUS *status)
558 {
559         char *q = prs_mem_get(ps, sizeof(uint32));
560         if (q == NULL)
561                 return False;
562
563         if (UNMARSHALLING(ps)) {
564                 if (ps->bigendian_data)
565                         *status = NT_STATUS(RIVAL(q,0));
566                 else
567                         *status = NT_STATUS(IVAL(q,0));
568         } else {
569                 if (ps->bigendian_data)
570                         RSIVAL(q,0,NT_STATUS_V(*status));
571                 else
572                         SIVAL(q,0,NT_STATUS_V(*status));
573         }
574
575         DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, 
576                  get_nt_error_msg(*status)));
577
578         ps->data_offset += sizeof(uint32);
579
580         return True;
581 }
582
583 /*******************************************************************
584  Stream a WERROR
585  ********************************************************************/
586
587 BOOL prs_werror(char *name, prs_struct *ps, int depth, WERROR *status)
588 {
589         char *q = prs_mem_get(ps, sizeof(uint32));
590         if (q == NULL)
591                 return False;
592
593         if (UNMARSHALLING(ps)) {
594                 if (ps->bigendian_data)
595                         *status = W_ERROR(RIVAL(q,0));
596                 else
597                         *status = W_ERROR(IVAL(q,0));
598         } else {
599                 if (ps->bigendian_data)
600                         RSIVAL(q,0,W_ERROR_V(*status));
601                 else
602                         SIVAL(q,0,W_ERROR_V(*status));
603         }
604
605         DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, 
606                  werror_str(*status)));
607
608         ps->data_offset += sizeof(uint32);
609
610         return True;
611 }
612
613
614 /******************************************************************
615  Stream an array of uint8s. Length is number of uint8s.
616  ********************************************************************/
617
618 BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
619 {
620         int i;
621         char *q = prs_mem_get(ps, len);
622         if (q == NULL)
623                 return False;
624
625         if (UNMARSHALLING(ps)) {
626                 for (i = 0; i < len; i++)
627                         data8s[i] = CVAL(q,i);
628         } else {
629                 for (i = 0; i < len; i++)
630                         SCVAL(q, i, data8s[i]);
631         }
632
633     DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset ,name));
634     if (charmode)
635                 print_asc(5, (unsigned char*)data8s, len);
636         else {
637         for (i = 0; i < len; i++)
638                         DEBUG(5,("%02x ", data8s[i]));
639         }
640     DEBUG(5,("\n"));
641
642         ps->data_offset += len;
643
644         return True;
645 }
646
647 /******************************************************************
648  Stream an array of uint16s. Length is number of uint16s.
649  ********************************************************************/
650
651 BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
652 {
653         int i;
654         char *q = prs_mem_get(ps, len * sizeof(uint16));
655         if (q == NULL)
656                 return False;
657
658         if (UNMARSHALLING(ps)) {
659                 if (ps->bigendian_data) {
660                         for (i = 0; i < len; i++)
661                                 data16s[i] = RSVAL(q, 2*i);
662                 } else {
663                         for (i = 0; i < len; i++)
664                                 data16s[i] = SVAL(q, 2*i);
665                 }
666         } else {
667                 if (ps->bigendian_data) {
668                         for (i = 0; i < len; i++)
669                                 RSSVAL(q, 2*i, data16s[i]);
670                 } else {
671                         for (i = 0; i < len; i++)
672                                 SSVAL(q, 2*i, data16s[i]);
673                 }
674         }
675
676         DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
677         if (charmode)
678                 print_asc(5, (unsigned char*)data16s, 2*len);
679         else {
680                 for (i = 0; i < len; i++)
681                         DEBUG(5,("%04x ", data16s[i]));
682         }
683     DEBUG(5,("\n"));
684
685         ps->data_offset += (len * sizeof(uint16));
686
687         return True;
688 }
689
690 /******************************************************************
691  Start using a function for streaming unicode chars. If unmarshalling,
692  output must be little-endian, if marshalling, input must be little-endian.
693  ********************************************************************/
694
695 static void dbg_rw_punival(BOOL charmode, char *name, int depth, prs_struct *ps,
696                                                         char *in_buf, char *out_buf, int len)
697 {
698         int i;
699
700         if (UNMARSHALLING(ps)) {
701                 if (ps->bigendian_data) {
702                         for (i = 0; i < len; i++)
703                                 SSVAL(out_buf,2*i,RSVAL(in_buf, 2*i));
704                 } else {
705                         for (i = 0; i < len; i++)
706                                 SSVAL(out_buf, 2*i, SVAL(in_buf, 2*i));
707                 }
708         } else {
709                 if (ps->bigendian_data) {
710                         for (i = 0; i < len; i++)
711                                 RSSVAL(in_buf, 2*i, SVAL(out_buf,2*i));
712                 } else {
713                         for (i = 0; i < len; i++)
714                                 SSVAL(in_buf, 2*i, SVAL(out_buf,2*i));
715                 }
716         }
717
718         DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
719         if (charmode)
720                 print_asc(5, (unsigned char*)out_buf, 2*len);
721         else {
722                 for (i = 0; i < len; i++)
723                         DEBUG(5,("%04x ", out_buf[i]));
724         }
725     DEBUG(5,("\n"));
726 }
727
728 /******************************************************************
729  Stream a unistr. Always little endian.
730  ********************************************************************/
731
732 BOOL prs_uint16uni(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
733 {
734         char *q = prs_mem_get(ps, len * sizeof(uint16));
735         if (q == NULL)
736                 return False;
737
738         dbg_rw_punival(charmode, name, depth, ps, q, (char *)data16s, len);
739         ps->data_offset += (len * sizeof(uint16));
740
741         return True;
742 }
743
744 /******************************************************************
745  Stream an array of uint32s. Length is number of uint32s.
746  ********************************************************************/
747
748 BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
749 {
750         int i;
751         char *q = prs_mem_get(ps, len * sizeof(uint32));
752         if (q == NULL)
753                 return False;
754
755         if (UNMARSHALLING(ps)) {
756                 if (ps->bigendian_data) {
757                         for (i = 0; i < len; i++)
758                                 data32s[i] = RIVAL(q, 4*i);
759                 } else {
760                         for (i = 0; i < len; i++)
761                                 data32s[i] = IVAL(q, 4*i);
762                 }
763         } else {
764                 if (ps->bigendian_data) {
765                         for (i = 0; i < len; i++)
766                                 RSIVAL(q, 4*i, data32s[i]);
767                 } else {
768                         for (i = 0; i < len; i++)
769                                 SIVAL(q, 4*i, data32s[i]);
770                 }
771         }
772
773         DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
774         if (charmode)
775                 print_asc(5, (unsigned char*)data32s, 4*len);
776         else {
777                 for (i = 0; i < len; i++)
778                         DEBUG(5,("%08x ", data32s[i]));
779         }
780     DEBUG(5,("\n"));
781
782         ps->data_offset += (len * sizeof(uint32));
783
784         return True;
785 }
786
787 /******************************************************************
788  Stream an array of unicode string, length/buffer specified separately,
789  in uint16 chars. The unicode string is already in little-endian format.
790  ********************************************************************/
791
792 BOOL prs_buffer5(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER5 *str)
793 {
794         char *p;
795         char *q = prs_mem_get(ps, str->buf_len * sizeof(uint16));
796         if (q == NULL)
797                 return False;
798
799         if (UNMARSHALLING(ps)) {
800                 str->buffer = (uint16 *)prs_alloc_mem(ps,str->buf_len * sizeof(uint16));
801                 if (str->buffer == NULL)
802                         return False;
803         }
804
805         /* If the string is empty, we don't have anything to stream */
806         if (str->buf_len==0)
807                 return True;
808
809         p = (char *)str->buffer;
810
811         dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len);
812         
813         ps->data_offset += (str->buf_len * sizeof(uint16));
814
815         return True;
816 }
817
818 /******************************************************************
819  Stream a "not" unicode string, length/buffer specified separately,
820  in byte chars. String is in little-endian format.
821  ********************************************************************/
822
823 BOOL prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str)
824 {
825         char *p;
826         char *q = prs_mem_get(ps, str->buf_len);
827         if (q == NULL)
828                 return False;
829
830         if (UNMARSHALLING(ps)) {
831                 str->buffer = (uint16 *)prs_alloc_mem(ps,str->buf_len);
832                 if (str->buffer == NULL)
833                         return False;
834         }
835
836         p = (char *)str->buffer;
837
838         dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len/2);
839         ps->data_offset += str->buf_len;
840
841         return True;
842 }
843
844 /******************************************************************
845  Stream a string, length/buffer specified separately,
846  in uint8 chars.
847  ********************************************************************/
848
849 BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
850 {
851         int i;
852         char *q = prs_mem_get(ps, str->str_str_len);
853         if (q == NULL)
854                 return False;
855
856         if (UNMARSHALLING(ps)) {
857                 str->buffer = (unsigned char *)prs_alloc_mem(ps,str->str_str_len);
858                 if (str->buffer == NULL)
859                         return False;
860         }
861
862         if (UNMARSHALLING(ps)) {
863                 for (i = 0; i < str->str_str_len; i++)
864                         str->buffer[i] = CVAL(q,i);
865         } else {
866                 for (i = 0; i < str->str_str_len; i++)
867                         SCVAL(q, i, str->buffer[i]);
868         }
869
870     DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
871     if (charmode)
872                 print_asc(5, (unsigned char*)str->buffer, str->str_str_len);
873         else {
874         for (i = 0; i < str->str_str_len; i++)
875                         DEBUG(5,("%02x ", str->buffer[i]));
876         }
877     DEBUG(5,("\n"));
878
879         ps->data_offset += str->str_str_len;
880
881         return True;
882 }
883
884 /******************************************************************
885  Stream a unicode string, length/buffer specified separately,
886  in uint16 chars. The unicode string is already in little-endian format.
887  ********************************************************************/
888
889 BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
890 {
891         char *p;
892         char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
893         if (q == NULL)
894                 return False;
895
896         /* If the string is empty, we don't have anything to stream */
897         if (str->uni_str_len==0)
898                 return True;
899
900         if (UNMARSHALLING(ps)) {
901                 str->buffer = (uint16 *)prs_alloc_mem(ps,str->uni_max_len * sizeof(uint16));
902                 if (str->buffer == NULL)
903                         return False;
904         }
905
906         p = (char *)str->buffer;
907
908         dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len);
909         
910         ps->data_offset += (str->uni_str_len * sizeof(uint16));
911
912         return True;
913 }
914
915 /******************************************************************
916  Stream a unicode string, length/buffer specified separately,
917  in uint16 chars. The unicode string is already in little-endian format.
918  ********************************************************************/
919
920 BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth)
921 {
922         char *p;
923         char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
924         if (q == NULL)
925                 return False;
926
927         if (UNMARSHALLING(ps)) {
928                 str->str.buffer = (uint16 *)prs_alloc_mem(ps,str->uni_str_len * sizeof(uint16));
929                 if (str->str.buffer == NULL)
930                         return False;
931         }
932
933         p = (char *)str->str.buffer;
934
935         dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len);
936         ps->data_offset += (str->uni_str_len * sizeof(uint16));
937
938         return True;
939 }
940
941 /*******************************************************************
942  Stream a unicode  null-terminated string. As the string is already
943  in little-endian format then do it as a stream of bytes.
944  ********************************************************************/
945
946 BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
947 {
948         int len = 0;
949         unsigned char *p = (unsigned char *)str->buffer;
950         uint8 *start;
951         char *q;
952         uint32 max_len;
953         uint16* ptr;
954
955         if (MARSHALLING(ps)) {
956
957                 for(len = 0; str->buffer[len] != 0; len++)
958                         ;
959
960                 q = prs_mem_get(ps, (len+1)*2);
961                 if (q == NULL)
962                         return False;
963
964                 start = (uint8*)q;
965
966                 for(len = 0; str->buffer[len] != 0; len++) 
967                 {
968                         if(ps->bigendian_data) 
969                         {
970                                 /* swap bytes - p is little endian, q is big endian. */
971                                 q[0] = (char)p[1];
972                                 q[1] = (char)p[0];
973                                 p += 2;
974                                 q += 2;
975                         } 
976                         else 
977                         {
978                                 q[0] = (char)p[0];
979                                 q[1] = (char)p[1];
980                                 p += 2;
981                                 q += 2;
982                         }
983                 }
984
985                 /*
986                  * even if the string is 'empty' (only an \0 char)
987                  * at this point the leading \0 hasn't been parsed.
988                  * so parse it now
989                  */
990
991                 q[0] = 0;
992                 q[1] = 0;
993                 q += 2;
994
995                 len++;
996
997                 dump_data(5+depth, (char *)start, len * 2);
998         }
999         else { /* unmarshalling */
1000         
1001                 uint32 alloc_len = 0;
1002                 q = prs_data_p(ps) + prs_offset(ps);
1003
1004                 /*
1005                  * Work out how much space we need and talloc it.
1006                  */
1007                 max_len = (ps->buffer_size - ps->data_offset)/sizeof(uint16);
1008
1009                 /* the test of the value of *ptr helps to catch the circumstance
1010                    where we have an emtpty (non-existent) string in the buffer */
1011                 for ( ptr = (uint16 *)q; *ptr && (alloc_len <= max_len); alloc_len++)
1012                         /* do nothing */ 
1013                         ;
1014
1015                 /* should we allocate anything at all? */
1016                 str->buffer = (uint16 *)prs_alloc_mem(ps,alloc_len * sizeof(uint16));
1017                 if ((str->buffer == NULL) && (alloc_len > 0))
1018                         return False;
1019
1020                 p = (unsigned char *)str->buffer;
1021
1022                 len = 0;
1023                 /* the (len < alloc_len) test is to prevent us from overwriting
1024                    memory that is not ours...if we get that far, we have a non-null
1025                    terminated string in the buffer and have messed up somewhere */
1026                 while ((len < alloc_len) && (*(uint16 *)q != 0))
1027                 {
1028                         if(ps->bigendian_data) 
1029                         {
1030                                 /* swap bytes - q is big endian, p is little endian. */
1031                                 p[0] = (unsigned char)q[1];
1032                                 p[1] = (unsigned char)q[0];
1033                                 p += 2;
1034                                 q += 2;
1035                         } else {
1036
1037                                 p[0] = (unsigned char)q[0];
1038                                 p[1] = (unsigned char)q[1];
1039                                 p += 2;
1040                                 q += 2;
1041                         }
1042
1043                         len++;
1044                 } 
1045                 if (len < alloc_len)
1046                 {
1047                         /* NULL terminate the UNISTR */
1048                         str->buffer[len++] = '\0';
1049                 }
1050         }
1051
1052         /* set the offset in the prs_struct; 'len' points to the
1053            terminiating NULL in the UNISTR so we need to go one more
1054            uint16 */
1055         ps->data_offset += (len)*2;
1056         
1057         return True;
1058 }
1059
1060
1061 /*******************************************************************
1062  Stream a null-terminated string.  len is strlen, and therefore does
1063  not include the null-termination character.
1064  ********************************************************************/
1065
1066 BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, int len, int max_buf_size)
1067 {
1068         char *q;
1069         int i;
1070
1071         len = MIN(len, (max_buf_size-1));
1072
1073         q = prs_mem_get(ps, len+1);
1074         if (q == NULL)
1075                 return False;
1076
1077         for(i = 0; i < len; i++) {
1078                 if (UNMARSHALLING(ps))
1079                         str[i] = q[i];
1080                 else
1081                         q[i] = str[i];
1082         }
1083
1084         /* The terminating null. */
1085         str[i] = '\0';
1086
1087         if (MARSHALLING(ps)) {
1088                 q[i] = '\0';
1089         }
1090
1091         ps->data_offset += len+1;
1092
1093         dump_data(5+depth, q, len);
1094
1095         return True;
1096 }
1097
1098 /*******************************************************************
1099  prs_uint16 wrapper. Call this and it sets up a pointer to where the
1100  uint16 should be stored, or gets the size if reading.
1101  ********************************************************************/
1102
1103 BOOL prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
1104 {
1105         *offset = ps->data_offset;
1106         if (UNMARSHALLING(ps)) {
1107                 /* reading. */
1108                 return prs_uint16(name, ps, depth, data16);
1109         } else {
1110                 char *q = prs_mem_get(ps, sizeof(uint16));
1111                 if(q ==NULL)
1112                         return False;
1113                 ps->data_offset += sizeof(uint16);
1114         }
1115         return True;
1116 }
1117
1118 /*******************************************************************
1119  prs_uint16 wrapper.  call this and it retrospectively stores the size.
1120  does nothing on reading, as that is already handled by ...._pre()
1121  ********************************************************************/
1122
1123 BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
1124                                 uint32 ptr_uint16, uint32 start_offset)
1125 {
1126         if (MARSHALLING(ps)) {
1127                 /* 
1128                  * Writing - temporarily move the offset pointer.
1129                  */
1130                 uint16 data_size = ps->data_offset - start_offset;
1131                 uint32 old_offset = ps->data_offset;
1132
1133                 ps->data_offset = ptr_uint16;
1134                 if(!prs_uint16(name, ps, depth, &data_size)) {
1135                         ps->data_offset = old_offset;
1136                         return False;
1137                 }
1138                 ps->data_offset = old_offset;
1139         } else {
1140                 ps->data_offset = start_offset + (uint32)(*data16);
1141         }
1142         return True;
1143 }
1144
1145 /*******************************************************************
1146  prs_uint32 wrapper. Call this and it sets up a pointer to where the
1147  uint32 should be stored, or gets the size if reading.
1148  ********************************************************************/
1149
1150 BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
1151 {
1152         *offset = ps->data_offset;
1153         if (UNMARSHALLING(ps) && (data32 != NULL)) {
1154                 /* reading. */
1155                 return prs_uint32(name, ps, depth, data32);
1156         } else {
1157                 ps->data_offset += sizeof(uint32);
1158         }
1159         return True;
1160 }
1161
1162 /*******************************************************************
1163  prs_uint32 wrapper.  call this and it retrospectively stores the size.
1164  does nothing on reading, as that is already handled by ...._pre()
1165  ********************************************************************/
1166
1167 BOOL prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
1168                                 uint32 ptr_uint32, uint32 data_size)
1169 {
1170         if (MARSHALLING(ps)) {
1171                 /* 
1172                  * Writing - temporarily move the offset pointer.
1173                  */
1174                 uint32 old_offset = ps->data_offset;
1175                 ps->data_offset = ptr_uint32;
1176                 if(!prs_uint32(name, ps, depth, &data_size)) {
1177                         ps->data_offset = old_offset;
1178                         return False;
1179                 }
1180                 ps->data_offset = old_offset;
1181         }
1182         return True;
1183 }
1184
1185 /* useful function to store a structure in rpc wire format */
1186 int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
1187 {
1188     TDB_DATA kbuf, dbuf;
1189     kbuf.dptr = keystr;
1190     kbuf.dsize = strlen(keystr)+1;
1191     dbuf.dptr = prs_data_p(ps);
1192     dbuf.dsize = prs_offset(ps);
1193     return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1194 }
1195
1196 /* useful function to fetch a structure into rpc wire format */
1197 int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *mem_ctx)
1198 {
1199     TDB_DATA kbuf, dbuf;
1200     kbuf.dptr = keystr;
1201     kbuf.dsize = strlen(keystr)+1;
1202
1203     dbuf = tdb_fetch(tdb, kbuf);
1204     if (!dbuf.dptr) return -1;
1205
1206     ZERO_STRUCTP(ps);
1207     prs_init(ps, 0, mem_ctx, UNMARSHALL);
1208     prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True);
1209
1210     return 0;
1211
1212
1213 /*******************************************************************
1214  hash a stream.
1215  ********************************************************************/
1216 BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16])
1217 {
1218         char *q;
1219
1220         q = prs_data_p(ps);
1221         q = &q[offset];
1222
1223 #ifdef DEBUG_PASSWORD
1224         DEBUG(100, ("prs_hash1\n"));
1225         dump_data(100, sess_key, 16);
1226         dump_data(100, q, 68);
1227 #endif
1228         SamOEMhash((uchar *) q, sess_key, 68);
1229
1230 #ifdef DEBUG_PASSWORD
1231         dump_data(100, q, 68);
1232 #endif
1233
1234         return True;
1235 }