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