4c52e15769c0e6e9f5c81e72b589251e76a49ef6
[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, 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         DEBUG(120,("_prs_string: string %s len %d max %d\n",
433                         str, len, max_buf_size));
434
435         do
436         {
437                 char *q;
438                 i++;
439
440                 q = mem_data(&(ps->data), ps->offset + i);
441                 if (q == NULL)
442                 {
443                         ps->error = True;
444                         return False;
445                 }
446
447                 if (i < len || len == 0)
448                 {
449                         RW_CVAL(ps->io, q, str[i], 0);
450                 }
451                 else
452                 {
453                         uint8 dummy = 0;
454                         RW_CVAL(ps->io, q, dummy,0);
455                 }
456
457         } while (i < max_buf_size && (len == 0 ? str[i] != 0 : i < len) );
458
459         DEBUG(120,("_prs_string: string %s len %d max %d\n",
460                         str, len, max_buf_size));
461
462         ps->offset += i+1;
463
464         dump_data(5+depth, (char *)start, i);
465
466         return True;
467 }
468
469 /*******************************************************************
470  prs_uint16 wrapper.  call this and it sets up a pointer to where the
471  uint16 should be stored, or gets the size if reading
472  ********************************************************************/
473 BOOL _prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
474 {
475         if (ps->error) return False;
476         (*offset) = ps->offset;
477         if (ps->io)
478         {
479                 /* reading. */
480                 return _prs_uint16(name, ps, depth, data16);
481         }
482         else
483         {
484                 ps->offset += sizeof(uint16);
485         }
486         return True;
487 }
488
489 /*******************************************************************
490  prs_uint16 wrapper.  call this and it retrospectively stores the size.
491  does nothing on reading, as that is already handled by ...._pre()
492  ********************************************************************/
493 BOOL _prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
494                                 uint32 ptr_uint16, uint32 start_offset)
495 {
496         if (ps->error) return False;
497         if (!ps->io)
498         {
499                 /* storing: go back and do a retrospective job.  i hate this */
500                 uint16 data_size = ps->offset - start_offset;
501                 uint32 old_offset = ps->offset;
502
503                 ps->offset = ptr_uint16;
504                 prs_uint16(name, ps, depth, &data_size);
505                 ps->offset = old_offset;
506         }
507         else
508         {
509                 ps->offset = start_offset + (*data16);
510         }
511         return True;
512 }
513
514 /*******************************************************************
515  prs_uint32 wrapper.  call this and it sets up a pointer to where the
516  uint32 should be stored, or gets the size if reading
517  ********************************************************************/
518 BOOL _prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
519 {
520         if (ps->error) return False;
521         (*offset) = ps->offset;
522         if (ps->io)
523         {
524                 /* reading. */
525                 return _prs_uint32(name, ps, depth, data32);
526         }
527         else
528         {
529                 ps->offset += sizeof(uint32);
530         }
531         return True;
532 }
533
534 /*******************************************************************
535  prs_uint32 wrapper.  call this and it retrospectively stores the size.
536  does nothing on reading, as that is already handled by ...._pre()
537  ********************************************************************/
538 BOOL _prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
539                                 uint32 ptr_uint32, uint32 data_size)
540 {
541         if (ps->error) return False;
542         if (!ps->io)
543         {
544                 /* storing: go back and do a retrospective job.  i hate this */
545                 uint32 old_offset = ps->offset;
546                 ps->offset = ptr_uint32;
547                 prs_uint32(name, ps, depth, &data_size);
548                 ps->offset = old_offset;
549         }
550         return True;
551 }
552