~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/rpc_parse/parse_prs.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
   Samba memory buffer functions
4
 
   Copyright (C) Andrew Tridgell              1992-1997
5
 
   Copyright (C) Luke Kenneth Casson Leighton 1996-1997
6
 
   Copyright (C) Jeremy Allison               1999
7
 
   Copyright (C) Andrew Bartlett              2003.
8
 
   
9
 
   This program is free software; you can redistribute it and/or modify
10
 
   it under the terms of the GNU General Public License as published by
11
 
   the Free Software Foundation; either version 3 of the License, or
12
 
   (at your option) any later version.
13
 
   
14
 
   This program is distributed in the hope that it will be useful,
15
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
   GNU General Public License for more details.
18
 
   
19
 
   You should have received a copy of the GNU General Public License
20
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 
*/
22
 
 
23
 
#include "includes.h"
24
 
#include "../librpc/gen_ndr/ndr_schannel.h"
25
 
 
26
 
#undef DBGC_CLASS
27
 
#define DBGC_CLASS DBGC_RPC_PARSE
28
 
 
29
 
/**
30
 
 * Dump a prs to a file: from the current location through to the end.
31
 
 **/
32
 
void prs_dump(const char *name, int v, prs_struct *ps)
33
 
{
34
 
        prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size);
35
 
}
36
 
 
37
 
/**
38
 
 * Dump from the start of the prs to the current location.
39
 
 **/
40
 
void prs_dump_before(const char *name, int v, prs_struct *ps)
41
 
{
42
 
        prs_dump_region(name, v, ps, 0, ps->data_offset);
43
 
}
44
 
 
45
 
/**
46
 
 * Dump everything from the start of the prs up to the current location.
47
 
 **/
48
 
void prs_dump_region(const char *name, int v, prs_struct *ps,
49
 
                     int from_off, int to_off)
50
 
{
51
 
        int fd, i;
52
 
        char *fname = NULL;
53
 
        ssize_t sz;
54
 
        if (DEBUGLEVEL < 50) return;
55
 
        for (i=1;i<100;i++) {
56
 
                if (v != -1) {
57
 
                        if (asprintf(&fname,"/tmp/%s_%d.%d.prs", name, v, i) < 0) {
58
 
                                return;
59
 
                        }
60
 
                } else {
61
 
                        if (asprintf(&fname,"/tmp/%s.%d.prs", name, i) < 0) {
62
 
                                return;
63
 
                        }
64
 
                }
65
 
                fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
66
 
                if (fd != -1 || errno != EEXIST) break;
67
 
        }
68
 
        if (fd != -1) {
69
 
                sz = write(fd, ps->data_p + from_off, to_off - from_off);
70
 
                i = close(fd);
71
 
                if ( (sz != to_off-from_off) || (i != 0) ) {
72
 
                        DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i ));
73
 
                } else {
74
 
                        DEBUG(0,("created %s\n", fname));
75
 
                }
76
 
        }
77
 
        SAFE_FREE(fname);
78
 
}
79
 
 
80
 
/*******************************************************************
81
 
 Debug output for parsing info
82
 
 
83
 
 XXXX side-effect of this function is to increase the debug depth XXXX.
84
 
 
85
 
********************************************************************/
86
 
 
87
 
void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
88
 
{
89
 
        DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(5+depth,depth), ps->data_offset, fn_name, desc));
90
 
}
91
 
 
92
 
/**
93
 
 * Initialise an expandable parse structure.
94
 
 *
95
 
 * @param size Initial buffer size.  If >0, a new buffer will be
96
 
 * created with malloc().
97
 
 *
98
 
 * @return False if allocation fails, otherwise True.
99
 
 **/
100
 
 
101
 
bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io)
102
 
{
103
 
        ZERO_STRUCTP(ps);
104
 
        ps->io = io;
105
 
        ps->bigendian_data = RPC_LITTLE_ENDIAN;
106
 
        ps->align = RPC_PARSE_ALIGN;
107
 
        ps->is_dynamic = False;
108
 
        ps->data_offset = 0;
109
 
        ps->buffer_size = 0;
110
 
        ps->data_p = NULL;
111
 
        ps->mem_ctx = ctx;
112
 
 
113
 
        if (size != 0) {
114
 
                ps->buffer_size = size;
115
 
                if((ps->data_p = (char *)SMB_MALLOC((size_t)size)) == NULL) {
116
 
                        DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size));
117
 
                        return False;
118
 
                }
119
 
                memset(ps->data_p, '\0', (size_t)size);
120
 
                ps->is_dynamic = True; /* We own this memory. */
121
 
        } else if (MARSHALLING(ps)) {
122
 
                /* If size is zero and we're marshalling we should allocate memory on demand. */
123
 
                ps->is_dynamic = True;
124
 
        }
125
 
 
126
 
        return True;
127
 
}
128
 
 
129
 
/*******************************************************************
130
 
 Delete the memory in a parse structure - if we own it.
131
 
 
132
 
 NOTE: Contrary to the somewhat confusing naming, this function is not
133
 
       intended for freeing memory allocated by prs_alloc_mem().  That memory
134
 
       is attached to the talloc context given by ps->mem_ctx.
135
 
 ********************************************************************/
136
 
 
137
 
void prs_mem_free(prs_struct *ps)
138
 
{
139
 
        if(ps->is_dynamic)
140
 
                SAFE_FREE(ps->data_p);
141
 
        ps->is_dynamic = False;
142
 
        ps->buffer_size = 0;
143
 
        ps->data_offset = 0;
144
 
}
145
 
 
146
 
/*******************************************************************
147
 
 Clear the memory in a parse structure.
148
 
 ********************************************************************/
149
 
 
150
 
void prs_mem_clear(prs_struct *ps)
151
 
{
152
 
        if (ps->buffer_size)
153
 
                memset(ps->data_p, '\0', (size_t)ps->buffer_size);
154
 
}
155
 
 
156
 
/*******************************************************************
157
 
 Allocate memory when unmarshalling... Always zero clears.
158
 
 ********************************************************************/
159
 
 
160
 
#if defined(PARANOID_MALLOC_CHECKER)
161
 
char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count)
162
 
#else
163
 
char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count)
164
 
#endif
165
 
{
166
 
        char *ret = NULL;
167
 
 
168
 
        if (size && count) {
169
 
                /* We can't call the type-safe version here. */
170
 
                ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count,
171
 
                                                 "parse_prs");
172
 
        }
173
 
        return ret;
174
 
}
175
 
 
176
 
/*******************************************************************
177
 
 Return the current talloc context we're using.
178
 
 ********************************************************************/
179
 
 
180
 
TALLOC_CTX *prs_get_mem_context(prs_struct *ps)
181
 
{
182
 
        return ps->mem_ctx;
183
 
}
184
 
 
185
 
/*******************************************************************
186
 
 Hand some already allocated memory to a prs_struct.
187
 
 ********************************************************************/
188
 
 
189
 
void prs_give_memory(prs_struct *ps, char *buf, uint32 size, bool is_dynamic)
190
 
{
191
 
        ps->is_dynamic = is_dynamic;
192
 
        ps->data_p = buf;
193
 
        ps->buffer_size = size;
194
 
}
195
 
 
196
 
/*******************************************************************
197
 
 Take some memory back from a prs_struct.
198
 
 ********************************************************************/
199
 
 
200
 
char *prs_take_memory(prs_struct *ps, uint32 *psize)
201
 
{
202
 
        char *ret = ps->data_p;
203
 
        if(psize)
204
 
                *psize = ps->buffer_size;
205
 
        ps->is_dynamic = False;
206
 
        prs_mem_free(ps);
207
 
        return ret;
208
 
}
209
 
 
210
 
/*******************************************************************
211
 
 Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary.
212
 
 ********************************************************************/
213
 
 
214
 
bool prs_set_buffer_size(prs_struct *ps, uint32 newsize)
215
 
{
216
 
        if (newsize > ps->buffer_size)
217
 
                return prs_force_grow(ps, newsize - ps->buffer_size);
218
 
 
219
 
        if (newsize < ps->buffer_size) {
220
 
                ps->buffer_size = newsize;
221
 
 
222
 
                /* newsize == 0 acts as a free and set pointer to NULL */
223
 
                if (newsize == 0) {
224
 
                        SAFE_FREE(ps->data_p);
225
 
                } else {
226
 
                        ps->data_p = (char *)SMB_REALLOC(ps->data_p, newsize);
227
 
 
228
 
                        if (ps->data_p == NULL) {
229
 
                                DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
230
 
                                        (unsigned int)newsize));
231
 
                                DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));
232
 
                                return False;
233
 
                        }
234
 
                }
235
 
        }
236
 
 
237
 
        return True;
238
 
}
239
 
 
240
 
/*******************************************************************
241
 
 Attempt, if needed, to grow a data buffer.
242
 
 Also depends on the data stream mode (io).
243
 
 ********************************************************************/
244
 
 
245
 
bool prs_grow(prs_struct *ps, uint32 extra_space)
246
 
{
247
 
        uint32 new_size;
248
 
 
249
 
        ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
250
 
 
251
 
        if(ps->data_offset + extra_space <= ps->buffer_size)
252
 
                return True;
253
 
 
254
 
        /*
255
 
         * We cannot grow the buffer if we're not reading
256
 
         * into the prs_struct, or if we don't own the memory.
257
 
         */
258
 
 
259
 
        if(UNMARSHALLING(ps) || !ps->is_dynamic) {
260
 
                DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
261
 
                                (unsigned int)extra_space));
262
 
                return False;
263
 
        }
264
 
        
265
 
        /*
266
 
         * Decide how much extra space we really need.
267
 
         */
268
 
 
269
 
        extra_space -= (ps->buffer_size - ps->data_offset);
270
 
        if(ps->buffer_size == 0) {
271
 
 
272
 
                /*
273
 
                 * Start with 128 bytes (arbitrary value), enough for small rpc
274
 
                 * requests
275
 
                 */
276
 
                new_size = MAX(128, extra_space);
277
 
 
278
 
                if((ps->data_p = (char *)SMB_MALLOC(new_size)) == NULL) {
279
 
                        DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
280
 
                        return False;
281
 
                }
282
 
                memset(ps->data_p, '\0', (size_t)new_size );
283
 
        } else {
284
 
                /*
285
 
                 * If the current buffer size is bigger than the space needed,
286
 
                 * just double it, else add extra_space. Always keep 64 bytes
287
 
                 * more, so that after we added a large blob we don't have to
288
 
                 * realloc immediately again.
289
 
                 */
290
 
                new_size = MAX(ps->buffer_size*2,
291
 
                               ps->buffer_size + extra_space + 64);
292
 
 
293
 
                if ((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) {
294
 
                        DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
295
 
                                (unsigned int)new_size));
296
 
                        return False;
297
 
                }
298
 
 
299
 
                memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
300
 
        }
301
 
        ps->buffer_size = new_size;
302
 
 
303
 
        return True;
304
 
}
305
 
 
306
 
/*******************************************************************
307
 
 Attempt to force a data buffer to grow by len bytes.
308
 
 This is only used when appending more data onto a prs_struct
309
 
 when reading an rpc reply, before unmarshalling it.
310
 
 ********************************************************************/
311
 
 
312
 
bool prs_force_grow(prs_struct *ps, uint32 extra_space)
313
 
{
314
 
        uint32 new_size = ps->buffer_size + extra_space;
315
 
 
316
 
        if(!UNMARSHALLING(ps) || !ps->is_dynamic) {
317
 
                DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
318
 
                                (unsigned int)extra_space));
319
 
                return False;
320
 
        }
321
 
 
322
 
        if((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) {
323
 
                DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",
324
 
                        (unsigned int)new_size));
325
 
                return False;
326
 
        }
327
 
 
328
 
        memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
329
 
 
330
 
        ps->buffer_size = new_size;
331
 
 
332
 
        return True;
333
 
}
334
 
 
335
 
/*******************************************************************
336
 
 Get the data pointer (external interface).
337
 
********************************************************************/
338
 
 
339
 
char *prs_data_p(prs_struct *ps)
340
 
{
341
 
        return ps->data_p;
342
 
}
343
 
 
344
 
/*******************************************************************
345
 
 Get the current data size (external interface).
346
 
 ********************************************************************/
347
 
 
348
 
uint32 prs_data_size(prs_struct *ps)
349
 
{
350
 
        return ps->buffer_size;
351
 
}
352
 
 
353
 
/*******************************************************************
354
 
 Fetch the current offset (external interface).
355
 
 ********************************************************************/
356
 
 
357
 
uint32 prs_offset(prs_struct *ps)
358
 
{
359
 
        return ps->data_offset;
360
 
}
361
 
 
362
 
/*******************************************************************
363
 
 Set the current offset (external interface).
364
 
 ********************************************************************/
365
 
 
366
 
bool prs_set_offset(prs_struct *ps, uint32 offset)
367
 
{
368
 
        if ((offset > ps->data_offset)
369
 
            && !prs_grow(ps, offset - ps->data_offset)) {
370
 
                return False;
371
 
        }
372
 
 
373
 
        ps->data_offset = offset;
374
 
        return True;
375
 
}
376
 
 
377
 
/*******************************************************************
378
 
 Append the data from one parse_struct into another.
379
 
 ********************************************************************/
380
 
 
381
 
bool prs_append_prs_data(prs_struct *dst, prs_struct *src)
382
 
{
383
 
        if (prs_offset(src) == 0)
384
 
                return True;
385
 
 
386
 
        if(!prs_grow(dst, prs_offset(src)))
387
 
                return False;
388
 
 
389
 
        memcpy(&dst->data_p[dst->data_offset], src->data_p, (size_t)prs_offset(src));
390
 
        dst->data_offset += prs_offset(src);
391
 
 
392
 
        return True;
393
 
}
394
 
 
395
 
/*******************************************************************
396
 
 Append some data from one parse_struct into another.
397
 
 ********************************************************************/
398
 
 
399
 
bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start,
400
 
                          uint32_t len)
401
 
{
402
 
        if (len == 0) {
403
 
                return true;
404
 
        }
405
 
 
406
 
        if(!prs_grow(dst, len)) {
407
 
                return false;
408
 
        }
409
 
 
410
 
        memcpy(&dst->data_p[dst->data_offset], ((char *)src_base) + start, (size_t)len);
411
 
        dst->data_offset += len;
412
 
        return true;
413
 
}
414
 
 
415
 
bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start,
416
 
                              uint32 len)
417
 
{
418
 
        return prs_append_some_data(dst, src->data_p, start, len);
419
 
}
420
 
 
421
 
/*******************************************************************
422
 
 Append the data from a buffer into a parse_struct.
423
 
 ********************************************************************/
424
 
 
425
 
bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len)
426
 
{
427
 
        if (len == 0)
428
 
                return True;
429
 
 
430
 
        if(!prs_grow(dst, len))
431
 
                return False;
432
 
 
433
 
        memcpy(&dst->data_p[dst->data_offset], src, (size_t)len);
434
 
        dst->data_offset += len;
435
 
 
436
 
        return True;
437
 
}
438
 
 
439
 
/*******************************************************************
440
 
 Copy some data from a parse_struct into a buffer.
441
 
 ********************************************************************/
442
 
 
443
 
bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len)
444
 
{
445
 
        if (len == 0)
446
 
                return True;
447
 
 
448
 
        if(!prs_mem_get(src, len))
449
 
                return False;
450
 
 
451
 
        memcpy(dst, &src->data_p[src->data_offset], (size_t)len);
452
 
        src->data_offset += len;
453
 
 
454
 
        return True;
455
 
}
456
 
 
457
 
/*******************************************************************
458
 
 Copy all the data from a parse_struct into a buffer.
459
 
 ********************************************************************/
460
 
 
461
 
bool prs_copy_all_data_out(char *dst, prs_struct *src)
462
 
{
463
 
        uint32 len = prs_offset(src);
464
 
 
465
 
        if (!len)
466
 
                return True;
467
 
 
468
 
        prs_set_offset(src, 0);
469
 
        return prs_copy_data_out(dst, src, len);
470
 
}
471
 
 
472
 
/*******************************************************************
473
 
 Set the data as X-endian (external interface).
474
 
 ********************************************************************/
475
 
 
476
 
void prs_set_endian_data(prs_struct *ps, bool endian)
477
 
{
478
 
        ps->bigendian_data = endian;
479
 
}
480
 
 
481
 
/*******************************************************************
482
 
 Align a the data_len to a multiple of align bytes - filling with
483
 
 zeros.
484
 
 ********************************************************************/
485
 
 
486
 
bool prs_align(prs_struct *ps)
487
 
{
488
 
        uint32 mod = ps->data_offset & (ps->align-1);
489
 
 
490
 
        if (ps->align != 0 && mod != 0) {
491
 
                uint32 extra_space = (ps->align - mod);
492
 
                if(!prs_grow(ps, extra_space))
493
 
                        return False;
494
 
                memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
495
 
                ps->data_offset += extra_space;
496
 
        }
497
 
 
498
 
        return True;
499
 
}
500
 
 
501
 
/******************************************************************
502
 
 Align on a 2 byte boundary
503
 
 *****************************************************************/
504
 
 
505
 
bool prs_align_uint16(prs_struct *ps)
506
 
{
507
 
        bool ret;
508
 
        uint8 old_align = ps->align;
509
 
 
510
 
        ps->align = 2;
511
 
        ret = prs_align(ps);
512
 
        ps->align = old_align;
513
 
        
514
 
        return ret;
515
 
}
516
 
 
517
 
/******************************************************************
518
 
 Align on a 8 byte boundary
519
 
 *****************************************************************/
520
 
 
521
 
bool prs_align_uint64(prs_struct *ps)
522
 
{
523
 
        bool ret;
524
 
        uint8 old_align = ps->align;
525
 
 
526
 
        ps->align = 8;
527
 
        ret = prs_align(ps);
528
 
        ps->align = old_align;
529
 
        
530
 
        return ret;
531
 
}
532
 
 
533
 
/******************************************************************
534
 
 Align on a specific byte boundary
535
 
 *****************************************************************/
536
 
 
537
 
bool prs_align_custom(prs_struct *ps, uint8 boundary)
538
 
{
539
 
        bool ret;
540
 
        uint8 old_align = ps->align;
541
 
 
542
 
        ps->align = boundary;
543
 
        ret = prs_align(ps);
544
 
        ps->align = old_align;
545
 
        
546
 
        return ret;
547
 
}
548
 
 
549
 
 
550
 
 
551
 
/*******************************************************************
552
 
 Align only if required (for the unistr2 string mainly)
553
 
 ********************************************************************/
554
 
 
555
 
bool prs_align_needed(prs_struct *ps, uint32 needed)
556
 
{
557
 
        if (needed==0)
558
 
                return True;
559
 
        else
560
 
                return prs_align(ps);
561
 
}
562
 
 
563
 
/*******************************************************************
564
 
 Ensure we can read/write to a given offset.
565
 
 ********************************************************************/
566
 
 
567
 
char *prs_mem_get(prs_struct *ps, uint32 extra_size)
568
 
{
569
 
        if(UNMARSHALLING(ps)) {
570
 
                /*
571
 
                 * If reading, ensure that we can read the requested size item.
572
 
                 */
573
 
                if (ps->data_offset + extra_size > ps->buffer_size) {
574
 
                        DEBUG(0,("prs_mem_get: reading data of size %u would overrun "
575
 
                                "buffer by %u bytes.\n",
576
 
                                (unsigned int)extra_size,
577
 
                                (unsigned int)(ps->data_offset + extra_size - ps->buffer_size) ));
578
 
                        return NULL;
579
 
                }
580
 
        } else {
581
 
                /*
582
 
                 * Writing - grow the buffer if needed.
583
 
                 */
584
 
                if(!prs_grow(ps, extra_size))
585
 
                        return NULL;
586
 
        }
587
 
        return &ps->data_p[ps->data_offset];
588
 
}
589
 
 
590
 
/*******************************************************************
591
 
 Change the struct type.
592
 
 ********************************************************************/
593
 
 
594
 
void prs_switch_type(prs_struct *ps, bool io)
595
 
{
596
 
        if ((ps->io ^ io) == True)
597
 
                ps->io=io;
598
 
}
599
 
 
600
 
/*******************************************************************
601
 
 Force a prs_struct to be dynamic even when it's size is 0.
602
 
 ********************************************************************/
603
 
 
604
 
void prs_force_dynamic(prs_struct *ps)
605
 
{
606
 
        ps->is_dynamic=True;
607
 
}
608
 
 
609
 
/*******************************************************************
610
 
 Associate a session key with a parse struct.
611
 
 ********************************************************************/
612
 
 
613
 
void prs_set_session_key(prs_struct *ps, const char sess_key[16])
614
 
{
615
 
        ps->sess_key = sess_key;
616
 
}
617
 
 
618
 
/*******************************************************************
619
 
 Stream a uint8.
620
 
 ********************************************************************/
621
 
 
622
 
bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
623
 
{
624
 
        char *q = prs_mem_get(ps, 1);
625
 
        if (q == NULL)
626
 
                return False;
627
 
 
628
 
        if (UNMARSHALLING(ps))
629
 
                *data8 = CVAL(q,0);
630
 
        else
631
 
                SCVAL(q,0,*data8);
632
 
 
633
 
        DEBUGADD(5,("%s%04x %s: %02x\n", tab_depth(5,depth), ps->data_offset, name, *data8));
634
 
 
635
 
        ps->data_offset += 1;
636
 
 
637
 
        return True;
638
 
}
639
 
 
640
 
/*******************************************************************
641
 
 Stream a uint16.
642
 
 ********************************************************************/
643
 
 
644
 
bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16)
645
 
{
646
 
        char *q = prs_mem_get(ps, sizeof(uint16));
647
 
        if (q == NULL)
648
 
                return False;
649
 
 
650
 
        if (UNMARSHALLING(ps)) {
651
 
                if (ps->bigendian_data)
652
 
                        *data16 = RSVAL(q,0);
653
 
                else
654
 
                        *data16 = SVAL(q,0);
655
 
        } else {
656
 
                if (ps->bigendian_data)
657
 
                        RSSVAL(q,0,*data16);
658
 
                else
659
 
                        SSVAL(q,0,*data16);
660
 
        }
661
 
 
662
 
        DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16));
663
 
 
664
 
        ps->data_offset += sizeof(uint16);
665
 
 
666
 
        return True;
667
 
}
668
 
 
669
 
/*******************************************************************
670
 
 Stream a uint32.
671
 
 ********************************************************************/
672
 
 
673
 
bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32)
674
 
{
675
 
        char *q = prs_mem_get(ps, sizeof(uint32));
676
 
        if (q == NULL)
677
 
                return False;
678
 
 
679
 
        if (UNMARSHALLING(ps)) {
680
 
                if (ps->bigendian_data)
681
 
                        *data32 = RIVAL(q,0);
682
 
                else
683
 
                        *data32 = IVAL(q,0);
684
 
        } else {
685
 
                if (ps->bigendian_data)
686
 
                        RSIVAL(q,0,*data32);
687
 
                else
688
 
                        SIVAL(q,0,*data32);
689
 
        }
690
 
 
691
 
        DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32));
692
 
 
693
 
        ps->data_offset += sizeof(uint32);
694
 
 
695
 
        return True;
696
 
}
697
 
 
698
 
/*******************************************************************
699
 
 Stream an int32.
700
 
 ********************************************************************/
701
 
 
702
 
bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32)
703
 
{
704
 
        char *q = prs_mem_get(ps, sizeof(int32));
705
 
        if (q == NULL)
706
 
                return False;
707
 
 
708
 
        if (UNMARSHALLING(ps)) {
709
 
                if (ps->bigendian_data)
710
 
                        *data32 = RIVALS(q,0);
711
 
                else
712
 
                        *data32 = IVALS(q,0);
713
 
        } else {
714
 
                if (ps->bigendian_data)
715
 
                        RSIVALS(q,0,*data32);
716
 
                else
717
 
                        SIVALS(q,0,*data32);
718
 
        }
719
 
 
720
 
        DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32));
721
 
 
722
 
        ps->data_offset += sizeof(int32);
723
 
 
724
 
        return True;
725
 
}
726
 
 
727
 
/*******************************************************************
728
 
 Stream a uint64_struct
729
 
 ********************************************************************/
730
 
bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64)
731
 
{
732
 
        if (UNMARSHALLING(ps)) {
733
 
                uint32 high, low;
734
 
 
735
 
                if (!prs_uint32(name, ps, depth+1, &low))
736
 
                        return False;
737
 
 
738
 
                if (!prs_uint32(name, ps, depth+1, &high))
739
 
                        return False;
740
 
 
741
 
                *data64 = ((uint64_t)high << 32) + low;
742
 
 
743
 
                return True;
744
 
        } else {
745
 
                uint32 high = (*data64) >> 32, low = (*data64) & 0xFFFFFFFF;
746
 
                return prs_uint32(name, ps, depth+1, &low) &&
747
 
                           prs_uint32(name, ps, depth+1, &high);
748
 
        }
749
 
}
750
 
 
751
 
/*******************************************************************
752
 
 Stream a DCE error code
753
 
 ********************************************************************/
754
 
 
755
 
bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status)
756
 
{
757
 
        char *q = prs_mem_get(ps, sizeof(uint32));
758
 
        if (q == NULL)
759
 
                return False;
760
 
 
761
 
        if (UNMARSHALLING(ps)) {
762
 
                if (ps->bigendian_data)
763
 
                        *status = NT_STATUS(RIVAL(q,0));
764
 
                else
765
 
                        *status = NT_STATUS(IVAL(q,0));
766
 
        } else {
767
 
                if (ps->bigendian_data)
768
 
                        RSIVAL(q,0,NT_STATUS_V(*status));
769
 
                else
770
 
                        SIVAL(q,0,NT_STATUS_V(*status));
771
 
        }
772
 
 
773
 
        DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name,
774
 
                 dcerpc_errstr(talloc_tos(), NT_STATUS_V(*status))));
775
 
 
776
 
        ps->data_offset += sizeof(uint32);
777
 
 
778
 
        return True;
779
 
}
780
 
 
781
 
/******************************************************************
782
 
 Stream an array of uint8s. Length is number of uint8s.
783
 
 ********************************************************************/
784
 
 
785
 
bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
786
 
{
787
 
        int i;
788
 
        char *q = prs_mem_get(ps, len);
789
 
        if (q == NULL)
790
 
                return False;
791
 
 
792
 
        if (UNMARSHALLING(ps)) {
793
 
                for (i = 0; i < len; i++)
794
 
                        data8s[i] = CVAL(q,i);
795
 
        } else {
796
 
                for (i = 0; i < len; i++)
797
 
                        SCVAL(q, i, data8s[i]);
798
 
        }
799
 
 
800
 
        DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name));
801
 
        if (charmode)
802
 
                print_asc(5, (unsigned char*)data8s, len);
803
 
        else {
804
 
                for (i = 0; i < len; i++)
805
 
                        DEBUGADD(5,("%02x ", data8s[i]));
806
 
        }
807
 
        DEBUGADD(5,("\n"));
808
 
 
809
 
        ps->data_offset += len;
810
 
 
811
 
        return True;
812
 
}
813
 
 
814
 
/******************************************************************
815
 
 Stream an array of uint16s. Length is number of uint16s.
816
 
 ********************************************************************/
817
 
 
818
 
bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
819
 
{
820
 
        int i;
821
 
        char *q = prs_mem_get(ps, len * sizeof(uint16));
822
 
        if (q == NULL)
823
 
                return False;
824
 
 
825
 
        if (UNMARSHALLING(ps)) {
826
 
                if (ps->bigendian_data) {
827
 
                        for (i = 0; i < len; i++)
828
 
                                data16s[i] = RSVAL(q, 2*i);
829
 
                } else {
830
 
                        for (i = 0; i < len; i++)
831
 
                                data16s[i] = SVAL(q, 2*i);
832
 
                }
833
 
        } else {
834
 
                if (ps->bigendian_data) {
835
 
                        for (i = 0; i < len; i++)
836
 
                                RSSVAL(q, 2*i, data16s[i]);
837
 
                } else {
838
 
                        for (i = 0; i < len; i++)
839
 
                                SSVAL(q, 2*i, data16s[i]);
840
 
                }
841
 
        }
842
 
 
843
 
        DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name));
844
 
        if (charmode)
845
 
                print_asc(5, (unsigned char*)data16s, 2*len);
846
 
        else {
847
 
                for (i = 0; i < len; i++)
848
 
                        DEBUGADD(5,("%04x ", data16s[i]));
849
 
        }
850
 
        DEBUGADD(5,("\n"));
851
 
 
852
 
        ps->data_offset += (len * sizeof(uint16));
853
 
 
854
 
        return True;
855
 
}
856
 
 
857
 
/******************************************************************
858
 
 Stream an array of uint32s. Length is number of uint32s.
859
 
 ********************************************************************/
860
 
 
861
 
bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
862
 
{
863
 
        int i;
864
 
        char *q = prs_mem_get(ps, len * sizeof(uint32));
865
 
        if (q == NULL)
866
 
                return False;
867
 
 
868
 
        if (UNMARSHALLING(ps)) {
869
 
                if (ps->bigendian_data) {
870
 
                        for (i = 0; i < len; i++)
871
 
                                data32s[i] = RIVAL(q, 4*i);
872
 
                } else {
873
 
                        for (i = 0; i < len; i++)
874
 
                                data32s[i] = IVAL(q, 4*i);
875
 
                }
876
 
        } else {
877
 
                if (ps->bigendian_data) {
878
 
                        for (i = 0; i < len; i++)
879
 
                                RSIVAL(q, 4*i, data32s[i]);
880
 
                } else {
881
 
                        for (i = 0; i < len; i++)
882
 
                                SIVAL(q, 4*i, data32s[i]);
883
 
                }
884
 
        }
885
 
 
886
 
        DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name));
887
 
        if (charmode)
888
 
                print_asc(5, (unsigned char*)data32s, 4*len);
889
 
        else {
890
 
                for (i = 0; i < len; i++)
891
 
                        DEBUGADD(5,("%08x ", data32s[i]));
892
 
        }
893
 
        DEBUGADD(5,("\n"));
894
 
 
895
 
        ps->data_offset += (len * sizeof(uint32));
896
 
 
897
 
        return True;
898
 
}
899
 
 
900
 
/*******************************************************************
901
 
 Stream a unicode  null-terminated string. As the string is already
902
 
 in little-endian format then do it as a stream of bytes.
903
 
 ********************************************************************/
904
 
 
905
 
bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str)
906
 
{
907
 
        unsigned int len = 0;
908
 
        unsigned char *p = (unsigned char *)str->buffer;
909
 
        uint8 *start;
910
 
        char *q;
911
 
        uint32 max_len;
912
 
        uint16* ptr;
913
 
 
914
 
        if (MARSHALLING(ps)) {
915
 
 
916
 
                for(len = 0; str->buffer[len] != 0; len++)
917
 
                        ;
918
 
 
919
 
                q = prs_mem_get(ps, (len+1)*2);
920
 
                if (q == NULL)
921
 
                        return False;
922
 
 
923
 
                start = (uint8*)q;
924
 
 
925
 
                for(len = 0; str->buffer[len] != 0; len++) {
926
 
                        if(ps->bigendian_data) {
927
 
                                /* swap bytes - p is little endian, q is big endian. */
928
 
                                q[0] = (char)p[1];
929
 
                                q[1] = (char)p[0];
930
 
                                p += 2;
931
 
                                q += 2;
932
 
                        } 
933
 
                        else 
934
 
                        {
935
 
                                q[0] = (char)p[0];
936
 
                                q[1] = (char)p[1];
937
 
                                p += 2;
938
 
                                q += 2;
939
 
                        }
940
 
                }
941
 
 
942
 
                /*
943
 
                 * even if the string is 'empty' (only an \0 char)
944
 
                 * at this point the leading \0 hasn't been parsed.
945
 
                 * so parse it now
946
 
                 */
947
 
 
948
 
                q[0] = 0;
949
 
                q[1] = 0;
950
 
                q += 2;
951
 
 
952
 
                len++;
953
 
 
954
 
                DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name));
955
 
                print_asc(5, (unsigned char*)start, 2*len);     
956
 
                DEBUGADD(5, ("\n"));
957
 
        }
958
 
        else { /* unmarshalling */
959
 
        
960
 
                uint32 alloc_len = 0;
961
 
                q = ps->data_p + prs_offset(ps);
962
 
 
963
 
                /*
964
 
                 * Work out how much space we need and talloc it.
965
 
                 */
966
 
                max_len = (ps->buffer_size - ps->data_offset)/sizeof(uint16);
967
 
 
968
 
                /* the test of the value of *ptr helps to catch the circumstance
969
 
                   where we have an emtpty (non-existent) string in the buffer */
970
 
                for ( ptr = (uint16 *)q; *ptr++ && (alloc_len <= max_len); alloc_len++)
971
 
                        /* do nothing */ 
972
 
                        ;
973
 
 
974
 
                if (alloc_len < max_len)
975
 
                        alloc_len += 1;
976
 
 
977
 
                /* should we allocate anything at all? */
978
 
                str->buffer = PRS_ALLOC_MEM(ps,uint16,alloc_len);
979
 
                if ((str->buffer == NULL) && (alloc_len > 0))
980
 
                        return False;
981
 
 
982
 
                p = (unsigned char *)str->buffer;
983
 
 
984
 
                len = 0;
985
 
                /* the (len < alloc_len) test is to prevent us from overwriting
986
 
                   memory that is not ours...if we get that far, we have a non-null
987
 
                   terminated string in the buffer and have messed up somewhere */
988
 
                while ((len < alloc_len) && (*(uint16 *)q != 0)) {
989
 
                        if(ps->bigendian_data) 
990
 
                        {
991
 
                                /* swap bytes - q is big endian, p is little endian. */
992
 
                                p[0] = (unsigned char)q[1];
993
 
                                p[1] = (unsigned char)q[0];
994
 
                                p += 2;
995
 
                                q += 2;
996
 
                        } else {
997
 
 
998
 
                                p[0] = (unsigned char)q[0];
999
 
                                p[1] = (unsigned char)q[1];
1000
 
                                p += 2;
1001
 
                                q += 2;
1002
 
                        }
1003
 
 
1004
 
                        len++;
1005
 
                } 
1006
 
                if (len < alloc_len) {
1007
 
                        /* NULL terminate the UNISTR */
1008
 
                        str->buffer[len++] = '\0';
1009
 
                }
1010
 
 
1011
 
                DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name));
1012
 
                print_asc(5, (unsigned char*)str->buffer, 2*len);       
1013
 
                DEBUGADD(5, ("\n"));
1014
 
        }
1015
 
 
1016
 
        /* set the offset in the prs_struct; 'len' points to the
1017
 
           terminiating NULL in the UNISTR so we need to go one more
1018
 
           uint16 */
1019
 
        ps->data_offset += (len)*2;
1020
 
        
1021
 
        return True;
1022
 
}
1023
 
 
1024
 
/*******************************************************************
1025
 
creates a new prs_struct containing a DATA_BLOB
1026
 
********************************************************************/
1027
 
bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
1028
 
{
1029
 
        if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL ))
1030
 
                return False;
1031
 
 
1032
 
 
1033
 
        if (!prs_copy_data_in(prs, (char *)blob->data, blob->length))
1034
 
                return False;
1035
 
 
1036
 
        return True;
1037
 
}
1038
 
 
1039
 
/*******************************************************************
1040
 
return the contents of a prs_struct in a DATA_BLOB
1041
 
********************************************************************/
1042
 
bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
1043
 
{
1044
 
        blob->length = prs_data_size(prs);
1045
 
        blob->data = (uint8 *)TALLOC_ZERO_SIZE(mem_ctx, blob->length);
1046
 
        
1047
 
        /* set the pointer at the end of the buffer */
1048
 
        prs_set_offset( prs, prs_data_size(prs) );
1049
 
 
1050
 
        if (!prs_copy_all_data_out((char *)blob->data, prs))
1051
 
                return False;
1052
 
        
1053
 
        return True;
1054
 
}