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