the first independent msrpc daemon - lsarpcd.
[samba.git] / source3 / 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, int level)
43 {
44         DEBUG(level,("ps: io %s align %d offset %d err %d data %p len %d\n",
45                 BOOLSTR(ps->io), ps->align, ps->offset, ps->error, ps->data,
46                 ps->data != NULL ? mem_buf_len(ps->data) : 0));
47 }
48
49 /*******************************************************************
50  initialise a parse structure
51  ********************************************************************/
52 void prs_init(prs_struct *ps, uint32 size,
53                                 uint8 align, uint32 margin,
54                                 BOOL io)
55 {
56         ps->io = io;
57         ps->align = align;
58         ps->offset = 0;
59         ps->error = False;
60
61         ps->data = NULL;
62         mem_buf_init(&(ps->data), margin);
63
64         if (size != 0)
65         {
66                 mem_alloc_data(ps->data, size);
67                 ps->data->offset.start = 0;
68                 ps->data->offset.end   = 0xffffffff;
69         }
70 }
71
72 /*******************************************************************
73  initialise a parse structure
74  ********************************************************************/
75 void prs_mem_free(prs_struct *ps)
76 {
77         mem_buf_free(&(ps->data));
78 }
79
80 /*******************************************************************
81  link one parsing structure to another
82  ********************************************************************/
83 void prs_link(prs_struct *prev, prs_struct *ps, prs_struct *next)
84 {
85         ps->data->offset.start = prev != NULL ? prev->data->offset.end : 0;
86         ps->data->offset.end   = ps->data->offset.start + ps->offset;
87         ps->data->next         = next != NULL ? next->data : NULL;
88 }
89
90 /*******************************************************************
91  align a pointer to a multiple of align_offset bytes.  looks like it
92  will work for offsets of 0, 2 and 4...
93  ********************************************************************/
94 void prs_align(prs_struct *ps)
95 {
96         int mod;
97         if (ps->error) return;
98         mod = ps->offset & (ps->align-1);
99         if (ps->align != 0 && mod != 0)
100         {
101                 ps->offset += ps->align - mod;
102         }
103 }
104
105 /*******************************************************************
106  attempt, if appropriate, to grow a data buffer.
107
108  depends on the data stream mode (io)
109  ********************************************************************/
110 BOOL prs_grow(prs_struct *ps)
111 {
112         if (ps->error) return False;
113         return mem_grow_data(&(ps->data), ps->io, ps->offset, False);
114 }
115
116
117 /*******************************************************************
118  stream a uint8
119  ********************************************************************/
120 BOOL _prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
121 {
122         char *q;
123         if (ps->error) return False;
124         q = mem_data(&(ps->data), ps->offset);
125         if (q == NULL)
126         {
127                 ps->error = True;
128                 return False;
129         }
130
131         DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8)
132         ps->offset += 1;
133
134         return True;
135 }
136
137 /*******************************************************************
138  stream a uint16
139  ********************************************************************/
140 BOOL _prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
141 {
142         char *q;
143         if (ps->error) return False;
144         q = mem_data(&(ps->data), ps->offset);
145         if (q == NULL)
146         {
147                 ps->error = True;
148                 return False;
149         }
150
151         DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16)
152         ps->offset += 2;
153
154         return True;
155 }
156
157 /*******************************************************************
158  hash a stream.
159  ********************************************************************/
160 BOOL _prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16])
161 {
162         char *q;
163         if (ps->error) return False;
164         q = mem_data(&(ps->data), ps->offset);
165         if (q == NULL)
166         {
167                 ps->error = True;
168                 return False;
169         }
170
171 #ifdef DEBUG_PASSWORD
172         DEBUG(100,("prs_hash1\n"));
173         dump_data(100, sess_key, 16);
174         dump_data(100, q, 68);
175 #endif
176         SamOEMhash((uchar*)q, sess_key, 2);
177 #ifdef DEBUG_PASSWORD
178         dump_data(100, q, 68);
179 #endif
180
181         return True;
182 }
183
184 /*******************************************************************
185  stream a uint32
186  ********************************************************************/
187 BOOL _prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
188 {
189         char *q;
190         if (ps->error) return False;
191         q = mem_data(&(ps->data), ps->offset);
192         if (q == NULL)
193         {
194                 ps->error = True;
195                 return False;
196         }
197
198         DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32)
199         ps->offset += 4;
200
201         return True;
202 }
203
204
205 /******************************************************************
206  stream an array of uint8s.  length is number of uint8s
207  ********************************************************************/
208 BOOL _prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
209 {
210         char *q;
211         int end_offset;
212         char *e;
213         if (ps->error) return False;
214         q = mem_data(&(ps->data), ps->offset);
215         end_offset = ps->offset + len * sizeof(uint8);
216         e = mem_data(&(ps->data), end_offset-1);
217
218         if (q == NULL || e == NULL) 
219         {
220                 ps->error = True;
221                 return False;
222         }
223
224         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len)
225         ps->offset = end_offset;
226
227         return True;
228 }
229
230 /******************************************************************
231  stream an array of uint16s.  length is number of uint16s
232  ********************************************************************/
233 BOOL _prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
234 {
235         char *q;
236         int end_offset;
237         char *e;
238         if (ps->error) return False;
239         q = mem_data(&(ps->data), ps->offset);
240         end_offset = ps->offset + len * sizeof(uint16);
241         e = mem_data(&(ps->data), end_offset-1);
242
243         if (q == NULL || e == NULL)
244         {
245                 ps->error = True;
246                 return False;
247         }
248
249         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, data16s, len)
250         ps->offset = end_offset;
251
252         return True;
253 }
254
255 /******************************************************************
256  stream an array of uint32s.  length is number of uint32s
257  ********************************************************************/
258 BOOL _prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
259 {
260         char *q;
261         int end_offset;
262         char *e;
263         if (ps->error) return False;
264         q = mem_data(&(ps->data), ps->offset);
265         end_offset = ps->offset + len * sizeof(uint32);
266         e = mem_data(&(ps->data), end_offset-1);
267
268         if (q == NULL || e == NULL)
269         {
270                 ps->error = True;
271                 return False;
272         }
273
274         DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len)
275         ps->offset = end_offset;
276
277         return True;
278 }
279
280 /******************************************************************
281  stream a "not" unicode string, length/buffer specified separately,
282  in byte chars
283  ********************************************************************/
284 BOOL _prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str)
285 {
286         char *q;
287         int end_offset;
288         char *e;
289         if (ps->error) return False;
290         q = mem_data(&(ps->data), ps->offset);
291         end_offset = ps->offset + str->buf_len;
292         e = mem_data(&(ps->data), end_offset-1);
293
294         if (q == NULL || e == NULL)
295         {
296                 ps->error = True;
297                 return False;
298         }
299
300         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->buf_len)
301         ps->offset = end_offset;
302
303         return True;
304 }
305
306 /******************************************************************
307  stream a string, length/buffer specified separately,
308  in uint8 chars.
309  ********************************************************************/
310 BOOL _prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
311 {
312         char *q;
313         int end_offset;
314         char *e;
315         if (ps->error) return False;
316         q = mem_data(&(ps->data), ps->offset);
317         end_offset = ps->offset + str->str_str_len * sizeof(uint8);
318         e = mem_data(&(ps->data), end_offset-1);
319
320         if (q == NULL || e == NULL)
321         {
322                 ps->error = True;
323                 return False;
324         }
325
326         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len)
327         ps->offset = end_offset;
328
329         return True;
330 }
331
332 /******************************************************************
333  stream a unicode string, length/buffer specified separately,
334  in uint16 chars.
335  ********************************************************************/
336 BOOL _prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
337 {
338         char *q;
339         int end_offset;
340         char *e;
341         if (ps->error) return False;
342         q = mem_data(&(ps->data), ps->offset);
343         end_offset = ps->offset + str->uni_str_len * sizeof(uint16);
344         e = mem_data(&(ps->data), end_offset-1);
345
346         if (q == NULL || e == NULL)
347         {
348                 ps->error = True;
349                 return False;
350         }
351
352         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_str_len)
353         ps->offset = end_offset;
354
355         return True;
356 }
357
358 /******************************************************************
359  stream a unicode string, length/buffer specified separately,
360  in uint16 chars.
361  ********************************************************************/
362 BOOL _prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth)
363 {
364         char *q;
365         int end_offset;
366         char *e;
367         if (ps->error) return False;
368         q = mem_data(&(ps->data), ps->offset);
369         end_offset = ps->offset + str->uni_str_len * sizeof(uint16);
370         e = mem_data(&(ps->data), end_offset-1);
371
372         if (q == NULL || e == NULL)
373         {
374                 ps->error = True;
375                 return False;
376         }
377
378         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->str.buffer, str->uni_str_len)
379         ps->offset = end_offset;
380
381         return True;
382 }
383
384 /*******************************************************************
385  stream a unicode  null-terminated string
386  ********************************************************************/
387 BOOL _prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
388 {
389         int i = -1;
390         uint8 *start;
391         if (ps->error) return False;
392         start = (uint8*)mem_data(&(ps->data), ps->offset);
393
394         do
395         {
396                 char *q;
397                 i++;
398                 q = mem_data(&(ps->data), ps->offset + i*2);
399                 if (q == NULL) 
400                 {
401                         ps->error = True;
402                         return False;
403                 }
404                 RW_SVAL(ps->io, q, str->buffer[i],0);
405         }
406         while ((((size_t)i) < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
407                      (str->buffer[i] != 0));
408
409
410         ps->offset += (i+1)*2;
411
412         dump_data(5+depth, (char *)start, i * 2);
413
414         return True;
415 }
416
417 /*******************************************************************
418  stream a null-terminated string.  len is strlen, and therefore does
419  not include the null-termination character.
420
421  len == 0 indicates variable length string
422  (up to max size of pstring - 1024 chars).
423
424  ********************************************************************/
425 BOOL _prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len, uint16 max_buf_size)
426 {
427         int i = -1; /* start off at zero after 1st i++ */
428         uint8 *start;
429         if (ps->error) return False;
430         start = (uint8*)mem_data(&(ps->data), ps->offset);
431
432         do
433         {
434                 char *q;
435                 i++;
436
437                 q = mem_data(&(ps->data), ps->offset + i);
438                 if (q == NULL)
439                 {
440                         ps->error = True;
441                         return False;
442                 }
443
444                 if (i < len || len == 0)
445                 {
446                         RW_CVAL(ps->io, q, str[i],0);
447                 }
448                 else
449                 {
450                         uint8 dummy = 0;
451                         RW_CVAL(ps->io, q, dummy,0);
452                 }
453
454         } while (i < max_buf_size && (len == 0 ? str[i] != 0 : i < len) );
455
456         ps->offset += i+1;
457
458         dump_data(5+depth, (char *)start, i);
459
460         return True;
461 }
462
463 /*******************************************************************
464  prs_uint16 wrapper.  call this and it sets up a pointer to where the
465  uint16 should be stored, or gets the size if reading
466  ********************************************************************/
467 BOOL _prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
468 {
469         if (ps->error) return False;
470         (*offset) = ps->offset;
471         if (ps->io)
472         {
473                 /* reading. */
474                 return _prs_uint16(name, ps, depth, data16);
475         }
476         else
477         {
478                 ps->offset += sizeof(uint16);
479         }
480         return True;
481 }
482
483 /*******************************************************************
484  prs_uint16 wrapper.  call this and it retrospectively stores the size.
485  does nothing on reading, as that is already handled by ...._pre()
486  ********************************************************************/
487 BOOL _prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
488                                 uint32 ptr_uint16, uint32 start_offset)
489 {
490         if (ps->error) return False;
491         if (!ps->io)
492         {
493                 /* storing: go back and do a retrospective job.  i hate this */
494                 uint16 data_size = ps->offset - start_offset;
495                 uint32 old_offset = ps->offset;
496
497                 ps->offset = ptr_uint16;
498                 prs_uint16(name, ps, depth, &data_size);
499                 ps->offset = old_offset;
500         }
501         else
502         {
503                 ps->offset = start_offset + (*data16);
504         }
505         return True;
506 }
507
508 /*******************************************************************
509  prs_uint32 wrapper.  call this and it sets up a pointer to where the
510  uint32 should be stored, or gets the size if reading
511  ********************************************************************/
512 BOOL _prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
513 {
514         if (ps->error) return False;
515         (*offset) = ps->offset;
516         if (ps->io)
517         {
518                 /* reading. */
519                 return _prs_uint32(name, ps, depth, data32);
520         }
521         else
522         {
523                 ps->offset += sizeof(uint32);
524         }
525         return True;
526 }
527
528 /*******************************************************************
529  prs_uint32 wrapper.  call this and it retrospectively stores the size.
530  does nothing on reading, as that is already handled by ...._pre()
531  ********************************************************************/
532 BOOL _prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
533                                 uint32 ptr_uint32, uint32 data_size)
534 {
535         if (ps->error) return False;
536         if (!ps->io)
537         {
538                 /* storing: go back and do a retrospective job.  i hate this */
539                 uint32 old_offset = ps->offset;
540                 ps->offset = ptr_uint32;
541                 prs_uint32(name, ps, depth, &data_size);
542                 ps->offset = old_offset;
543         }
544         return True;
545 }
546