delineation between smb and msrpc more marked. smbd now constructs
[tprouty/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-1999
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 extern int DEBUGLEVEL;
24
25 #include "includes.h"
26
27
28 /*******************************************************************
29  debug output for parsing info.
30
31  XXXX side-effect of this function is to increase the debug depth XXXX
32
33  ********************************************************************/
34 void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
35 {
36         DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc));
37 }
38
39 /*******************************************************************
40  debug a parse structure
41  ********************************************************************/
42 void prs_debug_out(prs_struct *ps, char *msg, int level)
43 {
44         DEBUG(level,("%s ps: io %s align %d offset %d err %d data %p len %d\n",
45                 msg, BOOLSTR(ps->io), ps->align, ps->offset, ps->error,
46                 ps->data,
47                 ps->data != NULL ? mem_buf_len(ps->data) : 0));
48 }
49
50 /*******************************************************************
51  initialise a parse structure
52  ********************************************************************/
53 void prs_init(prs_struct *ps, uint32 size,
54                                 uint8 align, uint32 margin,
55                                 BOOL io)
56 {
57         ps->io = io;
58         ps->align = align;
59         ps->offset = 0;
60         ps->error = False;
61
62         ps->data = NULL;
63         mem_buf_init(&(ps->data), margin);
64
65         if (size != 0)
66         {
67                 mem_alloc_data(ps->data, size);
68                 ps->data->offset.start = 0;
69                 ps->data->offset.end   = 0xffffffff;
70         }
71 }
72
73 /*******************************************************************
74  copy a parse structure
75  ********************************************************************/
76 BOOL prs_copy(prs_struct *ps, const prs_struct *from)
77 {
78         int len = mem_buf_len(from->data);
79         prs_init(ps, len, from->align, from->data->margin, from->io);
80         if (!mem_buf_copy(mem_data(&ps->data, 0), from->data, 0, len))
81         {
82                 return False;
83         }
84         ps->offset = len;
85         prs_link(NULL, ps, NULL);
86         return True;
87 }
88
89 /*******************************************************************
90  initialise a parse structure
91  ********************************************************************/
92 void prs_mem_free(prs_struct *ps)
93 {
94         mem_buf_free(&(ps->data));
95 }
96
97 /*******************************************************************
98  link one parsing structure to another
99  ********************************************************************/
100 void prs_link(prs_struct *prev, prs_struct *ps, prs_struct *next)
101 {
102         ps->data->offset.start = prev != NULL ? prev->data->offset.end : 0;
103         ps->data->offset.end   = ps->data->offset.start + ps->offset;
104         ps->data->next         = next != NULL ? next->data : NULL;
105
106         DEBUG(150,("prs_link: start %d end %d\n",
107                 ps->data->offset.start,
108                 ps->data->offset.end));
109 }
110
111 /*******************************************************************
112  align a pointer to a multiple of align_offset bytes.  looks like it
113  will work for offsets of 0, 2 and 4...
114  ********************************************************************/
115 void prs_align(prs_struct *ps)
116 {
117         int mod;
118         if (ps->error) return;
119         mod = ps->offset & (ps->align-1);
120         if (ps->align != 0 && mod != 0)
121         {
122                 ps->offset += ps->align - mod;
123         }
124 }
125
126 /*******************************************************************
127  attempt, if appropriate, to grow a data buffer.
128
129  depends on the data stream mode (io)
130  ********************************************************************/
131 BOOL prs_grow(prs_struct *ps, uint32 new_size)
132 {
133         if (ps->error) return False;
134         return mem_grow_data(&(ps->data), ps->io, new_size, False);
135 }
136
137 /*******************************************************************
138  lengthens a buffer by len bytes and copies data into it.
139  ********************************************************************/
140 BOOL prs_append_data(prs_struct *ps, const char *data, int len)
141 {
142         int prev_size = ps->data->data_used;
143         int new_size  = prev_size + len;
144         char *to;
145
146         mem_realloc_data(ps->data, new_size);
147         to = mem_data(&ps->data, prev_size);
148         if (to == NULL || ps->data->data_used != new_size)
149         {
150                 return False;
151         }
152         memcpy(to, data, len);
153
154         return True;
155 }
156
157 /*******************************************************************
158  stream a uint8
159  ********************************************************************/
160 BOOL _prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
161 {
162         char *q;
163         if (ps->error) return False;
164         prs_grow(ps, ps->offset + 1);
165         q = mem_data(&(ps->data), ps->offset);
166         if (q == NULL)
167         {
168                 ps->error = True;
169                 prs_debug_out(ps, "_prs_uint8 error", 5);
170                 return False;
171         }
172
173         DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8)
174         ps->offset += 1;
175
176
177         return True;
178 }
179
180 /*******************************************************************
181  stream a uint16
182  ********************************************************************/
183 BOOL _prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
184 {
185         char *q;
186         if (ps->error) return False;
187         prs_grow(ps, ps->offset + 2);
188         q = mem_data(&(ps->data), ps->offset);
189         if (q == NULL)
190         {
191                 ps->error = True;
192                 prs_debug_out(ps, "_prs_uint16 error", 5);
193                 return False;
194         }
195
196         DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16)
197         ps->offset += 2;
198
199         return True;
200 }
201
202 /*******************************************************************
203  hash a stream.
204  ********************************************************************/
205 BOOL _prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16])
206 {
207         char *q;
208         if (ps->error) return False;
209         q = mem_data(&(ps->data), ps->offset);
210         if (q == NULL)
211         {
212                 ps->error = True;
213                 prs_debug_out(ps, "_prs_hash1 error", 5);
214                 return False;
215         }
216
217 #ifdef DEBUG_PASSWORD
218         DEBUG(100,("prs_hash1\n"));
219         dump_data(100, sess_key, 16);
220         dump_data(100, q, 68);
221 #endif
222         SamOEMhash((uchar*)q, sess_key, 2);
223 #ifdef DEBUG_PASSWORD
224         dump_data(100, q, 68);
225 #endif
226
227         return True;
228 }
229
230 /*******************************************************************
231  stream a uint32
232  ********************************************************************/
233 BOOL _prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
234 {
235         char *q;
236         if (ps->error) return False;
237         prs_grow(ps, ps->offset + 4);
238         q = mem_data(&(ps->data), ps->offset);
239         if (q == NULL)
240         {
241                 ps->error = True;
242                 prs_debug_out(ps, "_prs_uint32 error", 5);
243                 return False;
244         }
245
246         DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32)
247         ps->offset += 4;
248
249         return True;
250 }
251
252
253 /******************************************************************
254  stream an array of uint8s.  length is number of uint8s
255  ********************************************************************/
256 BOOL _prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
257 {
258         char *q;
259         int end_offset;
260         char *e;
261         if (ps->error) return False;
262         end_offset = ps->offset + len * sizeof(uint8);
263         prs_grow(ps, end_offset);
264         q = mem_data(&(ps->data), ps->offset);
265         e = mem_data(&(ps->data), end_offset-1);
266
267         if (q == NULL || e == NULL) 
268         {
269                 ps->error = True;
270                 prs_debug_out(ps, "_prs_uint8s error", 5);
271                 return False;
272         }
273
274         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len)
275         ps->offset = end_offset;
276
277         return True;
278 }
279
280 /******************************************************************
281  stream an array of uint16s.  length is number of uint16s
282  ********************************************************************/
283 BOOL _prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
284 {
285         char *q;
286         int end_offset;
287         char *e;
288         if (ps->error) return False;
289         end_offset = ps->offset + len * sizeof(uint16);
290         prs_grow(ps, end_offset);
291         q = mem_data(&(ps->data), ps->offset);
292         e = mem_data(&(ps->data), end_offset-1);
293
294         if (q == NULL || e == NULL)
295         {
296                 ps->error = True;
297                 prs_debug_out(ps, "_prs_uint16s error", 5);
298                 return False;
299         }
300
301         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, data16s, len)
302         ps->offset = end_offset;
303
304         return True;
305 }
306
307 /******************************************************************
308  stream an array of uint32s.  length is number of uint32s
309  ********************************************************************/
310 BOOL _prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
311 {
312         char *q;
313         int end_offset;
314         char *e;
315         if (ps->error) return False;
316         end_offset = ps->offset + len * sizeof(uint32);
317         prs_grow(ps, end_offset);
318         q = mem_data(&(ps->data), ps->offset);
319         e = mem_data(&(ps->data), end_offset-1);
320
321         if (q == NULL || e == NULL)
322         {
323                 ps->error = True;
324                 prs_debug_out(ps, "_prs_uint32s error", 5);
325                 return False;
326         }
327
328         DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len)
329         ps->offset = end_offset;
330
331         return True;
332 }
333
334 /******************************************************************
335  stream a "not" unicode string, length/buffer specified separately,
336  in byte chars
337  ********************************************************************/
338 BOOL _prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str)
339 {
340         char *q;
341         int end_offset;
342         char *e;
343         if (ps->error) return False;
344         end_offset = ps->offset + str->buf_len * sizeof(uint8);
345         prs_grow(ps, end_offset);
346         q = mem_data(&(ps->data), ps->offset);
347         e = mem_data(&(ps->data), end_offset-1);
348
349         if (q == NULL || e == NULL)
350         {
351                 ps->error = True;
352                 prs_debug_out(ps, "_prs_buffer2 error", 5);
353                 return False;
354         }
355
356         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->buf_len)
357         ps->offset = end_offset;
358
359         return True;
360 }
361
362 /******************************************************************
363  stream a string, length/buffer specified separately,
364  in uint8 chars.
365  ********************************************************************/
366 BOOL _prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
367 {
368         char *q;
369         int end_offset;
370         char *e;
371         if (ps->error) return False;
372         end_offset = ps->offset + str->str_str_len * sizeof(uint8);
373         prs_grow(ps, end_offset);
374         q = mem_data(&(ps->data), ps->offset);
375         e = mem_data(&(ps->data), end_offset-1);
376
377         if (q == NULL || e == NULL)
378         {
379                 ps->error = True;
380                 prs_debug_out(ps, "_prs_string2 error", 5);
381                 return False;
382         }
383
384         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len)
385         ps->offset = end_offset;
386
387         return True;
388 }
389
390 /******************************************************************
391  stream a unicode string, length/buffer specified separately,
392  in uint16 chars.
393  ********************************************************************/
394 BOOL _prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
395 {
396         char *q;
397         int end_offset;
398         char *e;
399         if (ps->error) return False;
400         end_offset = ps->offset + str->uni_str_len * sizeof(uint16);
401         prs_grow(ps, end_offset);
402         q = mem_data(&(ps->data), ps->offset);
403         e = mem_data(&(ps->data), end_offset-1);
404
405         if (q == NULL || e == NULL)
406         {
407                 ps->error = True;
408                 prs_debug_out(ps, "_prs_unistr2 error", 5);
409                 return False;
410         }
411
412         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_str_len)
413         ps->offset = end_offset;
414
415         return True;
416 }
417
418 /******************************************************************
419  stream a unicode string, length/buffer specified separately,
420  in uint16 chars.
421  ********************************************************************/
422 BOOL _prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth)
423 {
424         char *q;
425         int end_offset;
426         char *e;
427         if (ps->error) return False;
428         end_offset = ps->offset + str->uni_str_len * sizeof(uint16);
429         prs_grow(ps, end_offset);
430         q = mem_data(&(ps->data), ps->offset);
431         e = mem_data(&(ps->data), end_offset-1);
432
433         if (q == NULL || e == NULL)
434         {
435                 ps->error = True;
436                 prs_debug_out(ps, "_prs_unistr3 error", 5);
437                 return False;
438         }
439
440         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->str.buffer, str->uni_str_len)
441         ps->offset = end_offset;
442
443         return True;
444 }
445
446 /*******************************************************************
447  stream a unicode  null-terminated string
448  ********************************************************************/
449 BOOL _prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
450 {
451         int i = -1;
452         uint8 *start;
453         if (ps->error) return False;
454         start = (uint8*)mem_data(&(ps->data), ps->offset);
455
456         do
457         {
458                 char *q;
459                 i++;
460                 prs_grow(ps, ps->offset + i*2);
461                 q = mem_data(&(ps->data), ps->offset + i*2);
462                 if (q == NULL) 
463                 {
464                         ps->error = True;
465                         prs_debug_out(ps, "_prs_unistr error", 5);
466                         return False;
467                 }
468                 RW_SVAL(ps->io, q, str->buffer[i],0);
469         }
470         while ((((size_t)i) < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
471                      (str->buffer[i] != 0));
472
473
474         ps->offset += (i+1)*2;
475
476         dump_data(5+depth, (char *)start, i * 2);
477
478         return True;
479 }
480
481 /*******************************************************************
482  stream a null-terminated string.  len is strlen, and therefore does
483  not include the null-termination character.
484
485  len == 0 indicates variable length string
486  (up to max size of pstring - 1024 chars).
487
488  ********************************************************************/
489 BOOL _prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len, uint16 max_buf_size)
490 {
491         int i = -1; /* start off at zero after 1st i++ */
492         uint8 *start;
493         if (ps->error) return False;
494         start = (uint8*)mem_data(&(ps->data), ps->offset);
495
496         DEBUG(120,("_prs_string: string %s len %d max %d\n",
497                         str, len, max_buf_size));
498
499         DEBUG(10,("%s%04x %s: ", tab_depth(depth), ps->offset, name != NULL ? name : ""));
500
501         do
502         {
503                 char *q;
504                 i++;
505
506                 prs_grow(ps, ps->offset + i);
507                 q = mem_data(&(ps->data), ps->offset + i);
508                 if (q == NULL)
509                 {
510                         ps->error = True;
511                         prs_debug_out(ps, "_prs_string error", 5);
512                         return False;
513                 }
514
515                 if (i < len || len == 0)
516                 {
517                         RW_CVAL(ps->io, q, str[i], 0);
518                 }
519                 else
520                 {
521                         uint8 dummy = 0;
522                         RW_CVAL(ps->io, q, dummy,0);
523                 }
524
525         } while (i < max_buf_size && (len == 0 ? str[i] != 0 : i < len) );
526
527         DEBUG(120,("_prs_string: string %s len %d max %d\n",
528                         str, len, max_buf_size));
529
530         ps->offset += i+1;
531
532         dump_data(5+depth, (char *)start, i);
533
534         return True;
535 }
536
537 /*******************************************************************
538  prs_uint16 wrapper.  call this and it sets up a pointer to where the
539  uint16 should be stored, or gets the size if reading
540  ********************************************************************/
541 BOOL _prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
542 {
543         if (ps->error) return False;
544         (*offset) = ps->offset;
545         if (ps->io)
546         {
547                 /* reading. */
548                 return _prs_uint16(name, ps, depth, data16);
549         }
550         else
551         {
552                 ps->offset += sizeof(uint16);
553         }
554         return True;
555 }
556
557 /*******************************************************************
558  prs_uint16 wrapper.  call this and it retrospectively stores the size.
559  does nothing on reading, as that is already handled by ...._pre()
560  ********************************************************************/
561 BOOL _prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
562                                 uint32 ptr_uint16, uint32 start_offset)
563 {
564         if (ps->error) return False;
565         if (!ps->io)
566         {
567                 /* storing: go back and do a retrospective job.  i hate this */
568                 uint16 data_size = ps->offset - start_offset;
569                 uint32 old_offset = ps->offset;
570
571                 ps->offset = ptr_uint16;
572                 prs_uint16(name, ps, depth, &data_size);
573                 ps->offset = old_offset;
574         }
575         else
576         {
577                 ps->offset = start_offset + (*data16);
578         }
579         return True;
580 }
581
582 /*******************************************************************
583  prs_uint32 wrapper.  call this and it sets up a pointer to where the
584  uint32 should be stored, or gets the size if reading
585  ********************************************************************/
586 BOOL _prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
587 {
588         if (ps->error) return False;
589         (*offset) = ps->offset;
590         if (ps->io)
591         {
592                 /* reading. */
593                 return _prs_uint32(name, ps, depth, data32);
594         }
595         else
596         {
597                 ps->offset += sizeof(uint32);
598         }
599         return True;
600 }
601
602 /*******************************************************************
603  prs_uint32 wrapper.  call this and it retrospectively stores the size.
604  does nothing on reading, as that is already handled by ...._pre()
605  ********************************************************************/
606 BOOL _prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
607                                 uint32 ptr_uint32, uint32 data_size)
608 {
609         if (ps->error) return False;
610         if (!ps->io)
611         {
612                 /* storing: go back and do a retrospective job.  i hate this */
613                 uint32 old_offset = ps->offset;
614                 ps->offset = ptr_uint32;
615                 prs_uint32(name, ps, depth, &data_size);
616                 ps->offset = old_offset;
617         }
618         return True;
619 }
620