e38b9d394aa7adc79dfe35c296ebe32a95d587a1
[samba.git] / source / librpc / ndr / ndr_basic.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    routines for marshalling/unmarshalling basic types
5
6    Copyright (C) Andrew Tridgell 2003
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 #include "includes.h"
24
25 #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
26 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
27 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
28 #define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
29 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
30 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
31 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
32
33
34 /*
35   check for data leaks from the server by looking for non-zero pad bytes
36   these could also indicate that real structure elements have been
37   mistaken for padding in the IDL
38 */
39 void ndr_check_padding(struct ndr_pull *ndr, size_t n)
40 {
41         size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
42         int i;
43         for (i=ndr->offset;i<ofs2;i++) {
44                 if (ndr->data[i] != 0) {
45                         break;
46                 }
47         }
48         if (i<ofs2) {
49                 DEBUG(0,("WARNING: Non-zero padding to %d: ", n));
50                 for (i=ndr->offset;i<ofs2;i++) {
51                         DEBUG(0,("%02x ", ndr->data[i]));
52                 }
53                 DEBUG(0,("\n"));
54         }
55
56 }
57
58 /*
59   parse a uint8
60 */
61 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, uint8_t *v)
62 {
63         NDR_PULL_NEED_BYTES(ndr, 1);
64         *v = CVAL(ndr->data, ndr->offset);
65         ndr->offset += 1;
66         return NT_STATUS_OK;
67 }
68
69
70 /*
71   parse a uint16
72 */
73 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, uint16_t *v)
74 {
75         NDR_PULL_ALIGN(ndr, 2);
76         NDR_PULL_NEED_BYTES(ndr, 2);
77         *v = NDR_SVAL(ndr, ndr->offset);
78         ndr->offset += 2;
79         return NT_STATUS_OK;
80 }
81
82
83 /*
84   parse a uint32_t
85 */
86 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, uint32_t *v)
87 {
88         NDR_PULL_ALIGN(ndr, 4);
89         NDR_PULL_NEED_BYTES(ndr, 4);
90         *v = NDR_IVAL(ndr, ndr->offset);
91         ndr->offset += 4;
92         return NT_STATUS_OK;
93 }
94
95 /*
96   parse a int32_t
97 */
98 NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int32_t *v)
99 {
100         NDR_PULL_ALIGN(ndr, 4);
101         NDR_PULL_NEED_BYTES(ndr, 4);
102         *v = NDR_IVALS(ndr, ndr->offset);
103         ndr->offset += 4;
104         return NT_STATUS_OK;
105 }
106
107 /*
108   parse a pointer
109 */
110 NTSTATUS ndr_pull_ptr(struct ndr_pull *ndr, uint32_t *v)
111 {
112         NTSTATUS status;
113         status = ndr_pull_uint32(ndr, v);
114         if (*v != 0) {
115                 ndr->ptr_count++;
116         }
117         return status;
118 }
119
120 /*
121   parse a udlong
122 */
123 NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, uint64_t *v)
124 {
125         NDR_PULL_ALIGN(ndr, 4);
126         NDR_PULL_NEED_BYTES(ndr, 8);
127         *v = NDR_IVAL(ndr, ndr->offset);
128         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
129         ndr->offset += 8;
130         return NT_STATUS_OK;
131 }
132
133 /*
134   parse a dlong
135 */
136 NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int64_t *v)
137 {
138         return ndr_pull_udlong(ndr, (uint64_t *)v);
139 }
140
141 /*
142   parse a hyper
143 */
144 NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, uint64_t *v)
145 {
146         NDR_PULL_ALIGN(ndr, 8);
147         return ndr_pull_udlong(ndr, v);
148 }
149
150 /*
151   pull a NTSTATUS
152 */
153 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, NTSTATUS *status)
154 {
155         uint32_t v;
156         NDR_CHECK(ndr_pull_uint32(ndr, &v));
157         *status = NT_STATUS(v);
158         return NT_STATUS_OK;
159 }
160
161 /*
162   push a NTSTATUS
163 */
164 NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, NTSTATUS status)
165 {
166         return ndr_push_uint32(ndr, NT_STATUS_V(status));
167 }
168
169 void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS *r)
170 {
171         ndr->print(ndr, "%-25s: %s", name, nt_errstr(*r));
172 }
173
174 /*
175   pull a WERROR
176 */
177 NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, WERROR *status)
178 {
179         uint32_t v;
180         NDR_CHECK(ndr_pull_uint32(ndr, &v));
181         *status = W_ERROR(v);
182         return NT_STATUS_OK;
183 }
184
185 /*
186   push a WERROR
187 */
188 NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, WERROR status)
189 {
190         return ndr_push_uint32(ndr, W_ERROR_V(status));
191 }
192
193 void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
194 {
195         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
196 }
197
198 /*
199   parse a set of bytes
200 */
201 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
202 {
203         NDR_PULL_NEED_BYTES(ndr, n);
204         memcpy(data, ndr->data + ndr->offset, n);
205         ndr->offset += n;
206         return NT_STATUS_OK;
207 }
208
209 /*
210   pull an array of uint8
211 */
212 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
213 {
214         if (!(ndr_flags & NDR_SCALARS)) {
215                 return NT_STATUS_OK;
216         }
217         return ndr_pull_bytes(ndr, data, n);
218 }
219
220
221 /*
222   pull an array of uint16
223 */
224 NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *data, uint32_t n)
225 {
226         uint32_t i;
227         if (!(ndr_flags & NDR_SCALARS)) {
228                 return NT_STATUS_OK;
229         }
230         for (i=0;i<n;i++) {
231                 NDR_CHECK(ndr_pull_uint16(ndr, &data[i]));
232         }
233         return NT_STATUS_OK;
234 }
235
236 /*
237   pull a const array of uint32_t
238 */
239 NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *data, uint32_t n)
240 {
241         uint32_t i;
242         if (!(ndr_flags & NDR_SCALARS)) {
243                 return NT_STATUS_OK;
244         }
245         for (i=0;i<n;i++) {
246                 NDR_CHECK(ndr_pull_uint32(ndr, &data[i]));
247         }
248         return NT_STATUS_OK;
249 }
250
251 /*
252   pull a const array of hyper
253 */
254 NTSTATUS ndr_pull_array_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *data, uint32_t n)
255 {
256         uint32_t i;
257         if (!(ndr_flags & NDR_SCALARS)) {
258                 return NT_STATUS_OK;
259         }
260         for (i=0;i<n;i++) {
261                 NDR_CHECK(ndr_pull_hyper(ndr, &data[i]));
262         }
263         return NT_STATUS_OK;
264 }
265
266 /*
267   pull a const array of WERROR
268 */
269 NTSTATUS ndr_pull_array_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *data, uint32_t n)
270 {
271         uint32_t i;
272         if (!(ndr_flags & NDR_SCALARS)) {
273                 return NT_STATUS_OK;
274         }
275         for (i=0;i<n;i++) {
276                 NDR_CHECK(ndr_pull_WERROR(ndr, &data[i]));
277         }
278         return NT_STATUS_OK;
279 }
280
281
282
283 /*
284   push a uint8
285 */
286 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, uint8_t v)
287 {
288         NDR_PUSH_NEED_BYTES(ndr, 1);
289         SCVAL(ndr->data, ndr->offset, v);
290         ndr->offset += 1;
291         return NT_STATUS_OK;
292 }
293
294 /*
295   push a uint16
296 */
297 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, uint16_t v)
298 {
299         NDR_PUSH_ALIGN(ndr, 2);
300         NDR_PUSH_NEED_BYTES(ndr, 2);
301         NDR_SSVAL(ndr, ndr->offset, v);
302         ndr->offset += 2;
303         return NT_STATUS_OK;
304 }
305
306 /*
307   push a uint32_t
308 */
309 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, uint32_t v)
310 {
311         NDR_PUSH_ALIGN(ndr, 4);
312         NDR_PUSH_NEED_BYTES(ndr, 4);
313         NDR_SIVAL(ndr, ndr->offset, v);
314         ndr->offset += 4;
315         return NT_STATUS_OK;
316 }
317
318 /*
319   push a int32_t
320 */
321 NTSTATUS ndr_push_int32(struct ndr_push *ndr, int32_t v)
322 {
323         NDR_PUSH_ALIGN(ndr, 4);
324         NDR_PUSH_NEED_BYTES(ndr, 4);
325         NDR_SIVALS(ndr, ndr->offset, v);
326         ndr->offset += 4;
327         return NT_STATUS_OK;
328 }
329
330 /*
331   push a uint64
332 */
333 NTSTATUS ndr_push_udlong(struct ndr_push *ndr, uint64_t v)
334 {
335         NDR_PUSH_ALIGN(ndr, 4);
336         NDR_PUSH_NEED_BYTES(ndr, 8);
337         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
338         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
339         ndr->offset += 8;
340         return NT_STATUS_OK;
341 }
342
343 /*
344   push a int64
345 */
346 NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int64_t v)
347 {
348         return ndr_push_udlong(ndr, (uint64_t)v);
349 }
350
351 /*
352   push a hyper
353 */
354 NTSTATUS ndr_push_hyper(struct ndr_push *ndr, uint64_t v)
355 {
356         NDR_PUSH_ALIGN(ndr, 8);
357         return ndr_push_udlong(ndr, v);
358 }
359
360 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
361 {
362         NDR_PUSH_ALIGN(ndr, size);
363         return NT_STATUS_OK;
364 }
365
366 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
367 {
368         NDR_PULL_ALIGN(ndr, size);
369         return NT_STATUS_OK;
370 }
371
372 /*
373   push some bytes
374 */
375 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
376 {
377         NDR_PUSH_NEED_BYTES(ndr, n);
378         memcpy(ndr->data + ndr->offset, data, n);
379         ndr->offset += n;
380         return NT_STATUS_OK;
381 }
382
383 /*
384   push some zero bytes
385 */
386 NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
387 {
388         NDR_PUSH_NEED_BYTES(ndr, n);
389         memset(ndr->data + ndr->offset, 0, n);
390         ndr->offset += n;
391         return NT_STATUS_OK;
392 }
393
394 /*
395   push an array of uint8
396 */
397 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
398 {
399         if (!(ndr_flags & NDR_SCALARS)) {
400                 return NT_STATUS_OK;
401         }
402         return ndr_push_bytes(ndr, data, n);
403 }
404
405 /*
406   push an array of uint16
407 */
408 NTSTATUS ndr_push_array_uint16(struct ndr_push *ndr, int ndr_flags, const uint16_t *data, uint32_t n)
409 {
410         int i;
411         if (!(ndr_flags & NDR_SCALARS)) {
412                 return NT_STATUS_OK;
413         }
414         for (i=0;i<n;i++) {
415                 NDR_CHECK(ndr_push_uint16(ndr, data[i]));
416         }
417         return NT_STATUS_OK;
418 }
419
420 /*
421   push an array of uint32_t
422 */
423 NTSTATUS ndr_push_array_uint32(struct ndr_push *ndr, int ndr_flags, const uint32_t *data, uint32_t n)
424 {
425         int i;
426         if (!(ndr_flags & NDR_SCALARS)) {
427                 return NT_STATUS_OK;
428         }
429         for (i=0;i<n;i++) {
430                 NDR_CHECK(ndr_push_uint32(ndr, data[i]));
431         }
432         return NT_STATUS_OK;
433 }
434
435 /*
436   push an array of hyper
437 */
438 NTSTATUS ndr_push_array_hyper(struct ndr_push *ndr, int ndr_flags, const uint64_t *data, uint32_t n)
439 {
440         int i;
441         if (!(ndr_flags & NDR_SCALARS)) {
442                 return NT_STATUS_OK;
443         }
444         for (i=0;i<n;i++) {
445                 NDR_CHECK(ndr_push_hyper(ndr, data[i]));
446         }
447         return NT_STATUS_OK;
448 }
449
450 /*
451   push an array of hyper
452 */
453 NTSTATUS ndr_push_array_WERROR(struct ndr_push *ndr, int ndr_flags, const WERROR *data, uint32_t n)
454 {
455         int i;
456         if (!(ndr_flags & NDR_SCALARS)) {
457                 return NT_STATUS_OK;
458         }
459         for (i=0;i<n;i++) {
460                 NDR_CHECK(ndr_push_WERROR(ndr, data[i]));
461         }
462         return NT_STATUS_OK;
463 }
464
465 /*
466   save the current position
467  */
468 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
469 {
470         save->offset = ndr->offset;
471 }
472
473 /*
474   restore the position
475  */
476 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
477 {
478         ndr->offset = save->offset;
479 }
480
481 /*
482   push a 1 if a pointer is non-NULL, otherwise 0
483 */
484 NTSTATUS ndr_push_ptr(struct ndr_push *ndr, const void *p)
485 {
486         uint32_t ptr = 0;
487         if (p) {
488                 /* we do this to ensure that we generate unique ref ids,
489                    which means we can handle the case where a MS programmer
490                    forgot to mark a pointer as unique */
491                 ndr->ptr_count++;
492                 ptr = ndr->ptr_count;
493         }
494         return ndr_push_uint32(ndr, ptr);
495 }
496
497
498 /*
499   pull a general string from the wire
500 */
501 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
502 {
503         char *as=NULL;
504         uint32_t len1, ofs, len2;
505         uint16_t len3;
506         int ret;
507         int chset = CH_UTF16;
508         unsigned byte_mul = 2;
509         unsigned flags = ndr->flags;
510         unsigned c_len_term = 0;
511
512         if (!(ndr_flags & NDR_SCALARS)) {
513                 return NT_STATUS_OK;
514         }
515
516         if (NDR_BE(ndr)) {
517                 chset = CH_UTF16BE;
518         }
519
520         if (flags & LIBNDR_FLAG_STR_ASCII) {
521                 chset = CH_DOS;
522                 byte_mul = 1;
523                 flags &= ~LIBNDR_FLAG_STR_ASCII;
524         }
525
526         if (flags & LIBNDR_FLAG_STR_UTF8) {
527                 chset = CH_UTF8;
528                 byte_mul = 1;
529                 flags &= ~LIBNDR_FLAG_STR_UTF8;
530         }
531
532         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
533         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
534                 c_len_term = 1;
535                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
536         }
537
538         switch (flags & LIBNDR_STRING_FLAGS) {
539         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
540         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
541                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
542                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
543                 if (ofs != 0) {
544                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
545                                               ndr->flags & LIBNDR_STRING_FLAGS);
546                 }
547                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
548                 if (len2 > len1) {
549                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
550                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
551                                               len1, ofs, len2);
552                 }
553                 if (len2 == 0) {
554                         *s = talloc_strdup(ndr, "");
555                         break;
556                 }
557                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
558                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
559                                             ndr->data+ndr->offset, 
560                                             (len2 + c_len_term)*byte_mul,
561                                             (void **)&as);
562                 if (ret == -1) {
563                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
564                                               "Bad character conversion");
565                 }
566                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
567
568                 /* this is a way of detecting if a string is sent with the wrong
569                    termination */
570                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
571                         if (strlen(as) < (len2 + c_len_term)) {
572                                 DEBUG(6,("short string '%s'\n", as));
573                         }
574                 } else {
575                         if (strlen(as) == (len2 + c_len_term)) {
576                                 DEBUG(6,("long string '%s'\n", as));
577                         }
578                 }
579                 *s = as;
580                 break;
581
582         case LIBNDR_FLAG_STR_SIZE4:
583         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
584                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
585                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
586                 if (len1 == 0) {
587                         *s = talloc_strdup(ndr, "");
588                         break;
589                 }
590                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
591                                             ndr->data+ndr->offset, 
592                                             (len1 + c_len_term)*byte_mul,
593                                             (void **)&as);
594                 if (ret == -1) {
595                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
596                                               "Bad character conversion");
597                 }
598                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
599
600                 /* this is a way of detecting if a string is sent with the wrong
601                    termination */
602                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
603                         if (strlen(as) < (len1 + c_len_term)) {
604                                 DEBUG(6,("short string '%s'\n", as));
605                         }
606                 } else {
607                         if (strlen(as) == (len1 + c_len_term)) {
608                                 DEBUG(6,("long string '%s'\n", as));
609                         }
610                 }
611                 *s = as;
612                 break;
613
614         case LIBNDR_FLAG_STR_LEN4:
615         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
616                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
617                 if (ofs != 0) {
618                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
619                                               ndr->flags & LIBNDR_STRING_FLAGS);
620                 }
621                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
622                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
623                 if (len1 == 0) {
624                         *s = talloc_strdup(ndr, "");
625                         break;
626                 }
627                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
628                                             ndr->data+ndr->offset, 
629                                             (len1 + c_len_term)*byte_mul,
630                                             (void **)&as);
631                 if (ret == -1) {
632                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
633                                               "Bad character conversion");
634                 }
635                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
636
637                 /* this is a way of detecting if a string is sent with the wrong
638                    termination */
639                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
640                         if (strlen(as) < (len1 + c_len_term)) {
641                                 DEBUG(6,("short string '%s'\n", as));
642                         }
643                 } else {
644                         if (strlen(as) == (len1 + c_len_term)) {
645                                 DEBUG(6,("long string '%s'\n", as));
646                         }
647                 }
648                 *s = as;
649                 break;
650
651
652         case LIBNDR_FLAG_STR_SIZE2:
653         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
654                 NDR_CHECK(ndr_pull_uint16(ndr, &len3));
655                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
656                 if (len3 == 0) {
657                         *s = talloc_strdup(ndr, "");
658                         break;
659                 }
660                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
661                                             ndr->data+ndr->offset, 
662                                             (len3 + c_len_term)*byte_mul,
663                                             (void **)&as);
664                 if (ret == -1) {
665                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
666                                               "Bad character conversion");
667                 }
668                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
669
670                 /* this is a way of detecting if a string is sent with the wrong
671                    termination */
672                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
673                         if (strlen(as) < (len3 + c_len_term)) {
674                                 DEBUG(6,("short string '%s'\n", as));
675                         }
676                 } else {
677                         if (strlen(as) == (len3 + c_len_term)) {
678                                 DEBUG(6,("long string '%s'\n", as));
679                         }
680                 }
681                 *s = as;
682                 break;
683
684         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
685                 NDR_CHECK(ndr_pull_uint16(ndr, &len3));
686                 NDR_PULL_NEED_BYTES(ndr, len3);
687                 if (len3 == 0) {
688                         *s = talloc_strdup(ndr, "");
689                         break;
690                 }
691                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
692                                             ndr->data+ndr->offset, 
693                                             len3,
694                                             (void **)&as);
695                 if (ret == -1) {
696                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
697                                               "Bad character conversion");
698                 }
699                 NDR_CHECK(ndr_pull_advance(ndr, len3));
700                 *s = as;
701                 break;
702
703         case LIBNDR_FLAG_STR_NULLTERM:
704                 if (byte_mul == 1) {
705                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
706                 } else {
707                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
708                 }
709                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
710                                             ndr->data+ndr->offset, 
711                                             len1,
712                                             (void **)&as);
713                 if (ret == -1) {
714                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
715                                               "Bad character conversion");
716                 }
717                 NDR_CHECK(ndr_pull_advance(ndr, len1));
718                 *s = as;
719                 break;
720
721         case LIBNDR_FLAG_STR_FIXLEN15:
722         case LIBNDR_FLAG_STR_FIXLEN32:
723                 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
724                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
725                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
726                                             ndr->data+ndr->offset, 
727                                             len1*byte_mul,
728                                             (void **)&as);
729                 if (ret == -1) {
730                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
731                                               "Bad character conversion");
732                 }
733                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
734                 *s = as;
735                 break;
736
737         default:
738                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
739                                       ndr->flags & LIBNDR_STRING_FLAGS);
740         }
741
742         return NT_STATUS_OK;
743 }
744
745
746 /*
747   push a general string onto the wire
748 */
749 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
750 {
751         ssize_t s_len, c_len, d_len;
752         int ret;
753         int chset = CH_UTF16;
754         unsigned flags = ndr->flags;
755         unsigned byte_mul = 2;
756         unsigned c_len_term = 1;
757
758         if (!(ndr_flags & NDR_SCALARS)) {
759                 return NT_STATUS_OK;
760         }
761
762         if (NDR_BE(ndr)) {
763                 chset = CH_UTF16BE;
764         }
765         
766         s_len = s?strlen(s):0;
767         c_len = s?strlen_m(s):0;
768
769         if (flags & LIBNDR_FLAG_STR_ASCII) {
770                 chset = CH_DOS;
771                 byte_mul = 1;
772                 flags &= ~LIBNDR_FLAG_STR_ASCII;
773         }
774
775         if (flags & LIBNDR_FLAG_STR_UTF8) {
776                 chset = CH_UTF8;
777                 byte_mul = 1;
778                 flags &= ~LIBNDR_FLAG_STR_UTF8;
779         }
780
781         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
782
783         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
784                 c_len_term = 0;
785                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
786         }
787
788         switch (flags & LIBNDR_STRING_FLAGS) {
789         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
790                 NDR_CHECK(ndr_push_uint32(ndr, c_len+c_len_term));
791                 NDR_CHECK(ndr_push_uint32(ndr, 0));
792                 NDR_CHECK(ndr_push_uint32(ndr, c_len+c_len_term));
793                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
794                 ret = convert_string(CH_UNIX, chset, 
795                                      s, s_len+1,
796                                      ndr->data+ndr->offset, 
797                                      byte_mul*(c_len+1));
798                 if (ret == -1) {
799                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
800                                               "Bad character conversion");
801                 }
802                 ndr->offset += byte_mul*(c_len+1);
803                 break;
804
805         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
806                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
807                 NDR_CHECK(ndr_push_uint32(ndr, 0));
808                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
809                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
810                 ret = convert_string(CH_UNIX, chset, 
811                                      s, s_len,
812                                      ndr->data+ndr->offset, c_len*byte_mul);
813                 if (ret == -1) {
814                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
815                                               "Bad character conversion");
816                 }
817                 ndr->offset += c_len*byte_mul;
818                 break;
819
820         case LIBNDR_FLAG_STR_LEN4:
821                 NDR_CHECK(ndr_push_uint32(ndr, 0));
822                 NDR_CHECK(ndr_push_uint32(ndr, c_len + c_len_term));
823                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
824                 ret = convert_string(CH_UNIX, chset, 
825                                      s, s_len + 1,
826                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
827                 if (ret == -1) {
828                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
829                                               "Bad character conversion");
830                 }
831                 ndr->offset += byte_mul*(c_len+1);
832                 break;
833
834         case LIBNDR_FLAG_STR_SIZE4:
835                 NDR_CHECK(ndr_push_uint32(ndr, c_len + c_len_term));
836                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
837                 ret = convert_string(CH_UNIX, chset, 
838                                      s, s_len + 1,
839                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
840                 if (ret == -1) {
841                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
842                                               "Bad character conversion");
843                 }
844                 ndr->offset += byte_mul*(c_len+1);
845                 break;
846
847         case LIBNDR_FLAG_STR_SIZE2:
848                 NDR_CHECK(ndr_push_uint16(ndr, c_len + c_len_term));
849                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
850                 ret = convert_string(CH_UNIX, chset, 
851                                      s, s_len + 1,
852                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
853                 if (ret == -1) {
854                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
855                                               "Bad character conversion");
856                 }
857                 ndr->offset += byte_mul*(c_len+1);
858                 break;
859
860         case LIBNDR_FLAG_STR_NULLTERM:
861                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
862                 ret = convert_string(CH_UNIX, chset, 
863                                      s, s_len+1,
864                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
865                 if (ret == -1) {
866                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
867                                               "Bad character conversion");
868                 }
869                 ndr->offset += byte_mul*(c_len+1);
870                 break;
871
872         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
873                 NDR_CHECK(ndr_push_uint16(ndr, c_len*byte_mul));
874                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
875                 ret = convert_string(CH_UNIX, chset, 
876                                      s, s_len,
877                                      ndr->data+ndr->offset, c_len*byte_mul);
878                 if (ret == -1) {
879                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
880                                               "Bad character conversion");
881                 }
882                 ndr->offset += c_len*byte_mul;
883                 break;
884
885         case LIBNDR_FLAG_STR_FIXLEN15:
886         case LIBNDR_FLAG_STR_FIXLEN32:
887                 d_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
888                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*d_len);
889                 ret = convert_string(CH_UNIX, chset, 
890                                      s, s_len + 1,
891                                      ndr->data+ndr->offset, byte_mul*d_len);
892                 if (ret == -1) {
893                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
894                                               "Bad character conversion");
895                 }
896                 ndr->offset += byte_mul*d_len;
897                 break;
898
899         default:
900                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
901                                       ndr->flags & LIBNDR_STRING_FLAGS);
902         }
903
904         return NT_STATUS_OK;
905 }
906
907 /*
908   push a general string onto the wire
909 */
910 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
911 {
912         size_t c_len;
913         unsigned flags = ndr->flags;
914         unsigned byte_mul = 2;
915         unsigned c_len_term = 1;
916
917         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
918                 return 32;
919         }
920         if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
921                 return 15;
922         }
923         
924         c_len = s?strlen_m(s):0;
925
926         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
927                 byte_mul = 1;
928         }
929
930         if (flags & LIBNDR_FLAG_STR_NOTERM) {
931                 c_len_term = 0;
932         }
933
934         c_len = c_len + c_len_term;
935
936         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
937                 c_len = c_len * byte_mul;
938         }
939
940         return c_len;
941 }
942
943
944 /*
945   push a NTTIME
946 */
947 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t)
948 {
949         NDR_CHECK(ndr_push_udlong(ndr, t));
950         return NT_STATUS_OK;
951 }
952
953 /*
954   pull a NTTIME
955 */
956 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t)
957 {
958         NDR_CHECK(ndr_pull_udlong(ndr, t));
959         return NT_STATUS_OK;
960 }
961
962 /*
963   push a NTTIME
964 */
965 NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, NTTIME t)
966 {
967         t /= 10000000;
968         NDR_CHECK(ndr_push_hyper(ndr, t));
969         return NT_STATUS_OK;
970 }
971
972 /*
973   pull a NTTIME_1sec
974 */
975 NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, NTTIME *t)
976 {
977         NDR_CHECK(ndr_pull_hyper(ndr, t));
978         (*t) *= 10000000;
979         return NT_STATUS_OK;
980 }
981
982 /*
983   pull a NTTIME_hyper
984 */
985 NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, NTTIME *t)
986 {
987         NDR_CHECK(ndr_pull_hyper(ndr, t));
988         return NT_STATUS_OK;
989 }
990
991 /*
992   push a NTTIME_hyper
993 */
994 NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, NTTIME t)
995 {
996         NDR_CHECK(ndr_push_hyper(ndr, t));
997         return NT_STATUS_OK;
998 }
999
1000 /*
1001   push a time_t
1002 */
1003 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t)
1004 {
1005         return ndr_push_uint32(ndr, t);
1006 }
1007
1008 /*
1009   pull a time_t
1010 */
1011 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, time_t *t)
1012 {
1013         uint32_t tt;
1014         NDR_CHECK(ndr_pull_uint32(ndr, &tt));
1015         *t = tt;
1016         return NT_STATUS_OK;
1017 }
1018
1019
1020 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
1021 {
1022         ndr->print(ndr, "%s: struct %s", name, type);
1023 }
1024
1025 void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
1026                     const char *val, uint_t value)
1027 {
1028         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
1029                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1030         } else {
1031                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1032         }
1033 }
1034
1035 void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint_t flag, uint_t value)
1036 {
1037         /* this is an attempt to support multi-bit bitmap masks */
1038         value &= flag;
1039
1040         while (!(flag & 1)) {
1041                 flag >>= 1;
1042                 value >>= 1;
1043         }       
1044         if (flag == 1) {
1045                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
1046         } else {
1047                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
1048         }
1049 }
1050
1051 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
1052 {
1053         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
1054 }
1055
1056 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
1057 {
1058         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
1059 }
1060
1061 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
1062 {
1063         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1064 }
1065
1066 void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
1067 {
1068         ndr->print(ndr, "%-25s: %d", name, v);
1069 }
1070
1071 void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
1072 {
1073         ndr->print(ndr, "%-25s: 0x%08x%08x (%llu)", name,
1074                    (uint32_t)(v >> 32),
1075                    (uint32_t)(v & 0xFFFFFFFF),
1076                    v);
1077 }
1078
1079 void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
1080 {
1081         ndr->print(ndr, "%-25s: 0x%08x%08x (%lld)", name, 
1082                    (uint32_t)(v >> 32), 
1083                    (uint32_t)(v & 0xFFFFFFFF),
1084                    v);
1085 }
1086
1087 void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
1088 {
1089         ndr_print_dlong(ndr, name, v);
1090 }
1091
1092 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1093 {
1094         if (p) {
1095                 ndr->print(ndr, "%-25s: *", name);
1096         } else {
1097                 ndr->print(ndr, "%-25s: NULL", name);
1098         }
1099 }
1100
1101 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
1102 {
1103         if (s) {
1104                 ndr->print(ndr, "%-25s: '%s'", name, s);
1105         } else {
1106                 ndr->print(ndr, "%-25s: NULL", name);
1107         }
1108 }
1109
1110 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1111 {
1112         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1113 }
1114
1115 void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1116 {
1117         /* this is a standard NTTIME here
1118          * as it's already converted in the pull/push code
1119          */
1120         ndr_print_NTTIME(ndr, name, t);
1121 }
1122
1123 void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
1124 {
1125         ndr_print_NTTIME(ndr, name, t);
1126 }
1127
1128 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1129 {
1130         if (t == (time_t)-1 || t == 0) {
1131                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1132         } else {
1133                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1134         }
1135 }
1136
1137 void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1138 {
1139         ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1140 }
1141
1142 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1143 {
1144         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1145 }
1146
1147 void ndr_print_array_WERROR(struct ndr_print *ndr, const char *name, 
1148                             const WERROR *data, uint32_t count)
1149 {
1150         int i;
1151
1152         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1153         ndr->depth++;
1154         for (i=0;i<count;i++) {
1155                 char *idx=NULL;
1156                 asprintf(&idx, "[%d]", i);
1157                 if (idx) {
1158                         ndr_print_WERROR(ndr, idx, data[i]);
1159                         free(idx);
1160                 }
1161         }
1162         ndr->depth--;   
1163 }
1164
1165 void ndr_print_array_hyper(struct ndr_print *ndr, const char *name, 
1166                             const uint64_t *data, uint32_t count)
1167 {
1168         int i;
1169
1170         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1171         ndr->depth++;
1172         for (i=0;i<count;i++) {
1173                 char *idx=NULL;
1174                 asprintf(&idx, "[%d]", i);
1175                 if (idx) {
1176                         ndr_print_hyper(ndr, idx, data[i]);
1177                         free(idx);
1178                 }
1179         }
1180         ndr->depth--;   
1181 }
1182
1183 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
1184                             const uint32_t *data, uint32_t count)
1185 {
1186         int i;
1187
1188         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1189         ndr->depth++;
1190         for (i=0;i<count;i++) {
1191                 char *idx=NULL;
1192                 asprintf(&idx, "[%d]", i);
1193                 if (idx) {
1194                         ndr_print_uint32(ndr, idx, data[i]);
1195                         free(idx);
1196                 }
1197         }
1198         ndr->depth--;   
1199 }
1200
1201 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
1202                             const uint16_t *data, uint32_t count)
1203 {
1204         int i;
1205
1206         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1207         ndr->depth++;
1208         for (i=0;i<count;i++) {
1209                 char *idx=NULL;
1210                 asprintf(&idx, "[%d]", i);
1211                 if (idx) {
1212                         ndr_print_uint16(ndr, idx, data[i]);
1213                         free(idx);
1214                 }
1215         }
1216         ndr->depth--;   
1217 }
1218
1219 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1220                            const uint8_t *data, uint32_t count)
1221 {
1222         int i;
1223
1224         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1225                 char s[1202];
1226                 for (i=0;i<count;i++) {
1227                         snprintf(&s[i*2], 3, "%02x", data[i]);
1228                 }
1229                 s[i*2] = 0;
1230                 ndr->print(ndr, "%-25s: %s", name, s);
1231                 return;
1232         }
1233
1234         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1235         ndr->depth++;
1236         for (i=0;i<count;i++) {
1237                 char *idx=NULL;
1238                 asprintf(&idx, "[%d]", i);
1239                 if (idx) {
1240                         ndr_print_uint8(ndr, idx, data[i]);
1241                         free(idx);
1242                 }
1243         }
1244         ndr->depth--;   
1245 }
1246
1247 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1248 {
1249         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
1250         if (r.length) {
1251                 dump_data(10, r.data, r.length);
1252         }
1253 }
1254
1255
1256 /*
1257   push a DATA_BLOB onto the wire. 
1258 */
1259 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob)
1260 {
1261         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1262                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1263                         blob.length = NDR_ALIGN(ndr, 2);
1264                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1265                         blob.length = NDR_ALIGN(ndr, 4);
1266                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1267                         blob.length = NDR_ALIGN(ndr, 8);
1268                 }
1269                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1270                 data_blob_clear(&blob);
1271         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1272                 NDR_CHECK(ndr_push_uint32(ndr, blob.length));
1273         }
1274         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1275         return NT_STATUS_OK;
1276 }
1277
1278 /*
1279   pull a DATA_BLOB from the wire. 
1280 */
1281 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob)
1282 {
1283         uint32_t length;
1284
1285         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1286                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1287                         length = NDR_ALIGN(ndr, 2);
1288                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1289                         length = NDR_ALIGN(ndr, 4);
1290                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1291                         length = NDR_ALIGN(ndr, 8);
1292                 }
1293                 if (ndr->data_size - ndr->offset < length) {
1294                         length = ndr->data_size - ndr->offset;
1295                 }
1296         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1297                 length = ndr->data_size - ndr->offset;
1298         } else {
1299                 NDR_CHECK(ndr_pull_uint32(ndr, &length));
1300         }
1301         NDR_PULL_NEED_BYTES(ndr, length);
1302         *blob = data_blob_talloc(ndr, ndr->data+ndr->offset, length);
1303         ndr->offset += length;
1304         return NT_STATUS_OK;
1305 }
1306
1307 uint32 ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1308 {
1309         return ret + data->length;
1310 }
1311
1312 uint32 ndr_size_string(int ret, const char * const* string, int flags) 
1313 {
1314         /* FIXME: Is this correct for all strings ? */
1315         if(!(*string)) return ret;
1316         return ret+strlen(*string)+1;
1317 }