315dc7605905da7f83bd53701102503fdbd1ca42
[samba.git] / source4 / 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 uint64
122 */
123 NTSTATUS ndr_pull_uint64(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 int64
135 */
136 NTSTATUS ndr_pull_int64(struct ndr_pull *ndr, int64_t *v)
137 {
138         return ndr_pull_uint64(ndr, (uint64_t *)v);
139 }
140
141 /*
142   parse a HYPER_T
143 */
144 NTSTATUS ndr_pull_HYPER_T(struct ndr_pull *ndr, HYPER_T *v)
145 {
146         NDR_PULL_ALIGN(ndr, 8);
147         return ndr_pull_uint64(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_T
253 */
254 NTSTATUS ndr_pull_array_HYPER_T(struct ndr_pull *ndr, int ndr_flags, HYPER_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_T(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_uint64(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_int64(struct ndr_push *ndr, int64_t v)
347 {
348         return ndr_push_uint64(ndr, (uint64_t)v);
349 }
350
351 /*
352   push a HYPER_T
353 */
354 NTSTATUS ndr_push_HYPER_T(struct ndr_push *ndr, HYPER_T v)
355 {
356         NDR_PUSH_ALIGN(ndr, 8);
357         return ndr_push_uint64(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_T
437 */
438 NTSTATUS ndr_push_array_HYPER_T(struct ndr_push *ndr, int ndr_flags, const HYPER_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_T(ndr, data[i]));
446         }
447         return NT_STATUS_OK;
448 }
449
450 /*
451   push an array of HYPER_T
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_FIXLEN32:
722                 len1 = 32;
723                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
724                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
725                                             ndr->data+ndr->offset, 
726                                             len1*byte_mul,
727                                             (void **)&as);
728                 if (ret == -1) {
729                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
730                                               "Bad character conversion");
731                 }
732                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
733                 *s = as;
734                 break;
735
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;
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_FIXLEN32:
886                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*32);
887                 ret = convert_string(CH_UNIX, chset, 
888                                      s, s_len + 1,
889                                      ndr->data+ndr->offset, byte_mul*32);
890                 if (ret == -1) {
891                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
892                                               "Bad character conversion");
893                 }
894                 ndr->offset += byte_mul*32;
895                 break;
896
897         default:
898                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
899                                       ndr->flags & LIBNDR_STRING_FLAGS);
900         }
901
902         return NT_STATUS_OK;
903 }
904
905 /*
906   push a general string onto the wire
907 */
908 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
909 {
910         size_t c_len;
911         unsigned flags = ndr->flags;
912         unsigned byte_mul = 2;
913         unsigned c_len_term = 1;
914
915         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
916                 return 32;
917         }
918         
919         c_len = s?strlen_m(s):0;
920
921         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
922                 byte_mul = 1;
923         }
924
925         if (flags & LIBNDR_FLAG_STR_NOTERM) {
926                 c_len_term = 0;
927         }
928
929         c_len = c_len + c_len_term;
930
931         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
932                 c_len = c_len * byte_mul;
933         }
934
935         return c_len;
936 }
937
938
939 /*
940   push a NTTIME
941 */
942 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t)
943 {
944         NDR_CHECK(ndr_push_uint64(ndr, t));
945         return NT_STATUS_OK;
946 }
947
948 /*
949   pull a NTTIME
950 */
951 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t)
952 {
953         NDR_CHECK(ndr_pull_uint64(ndr, t));
954         return NT_STATUS_OK;
955 }
956
957 /*
958   push a NTTIME
959 */
960 NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, NTTIME t)
961 {
962         t /= 10000000;
963         NDR_CHECK(ndr_push_HYPER_T(ndr, t));
964         return NT_STATUS_OK;
965 }
966
967 /*
968   pull a NTTIME
969 */
970 NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, NTTIME *t)
971 {
972         NDR_CHECK(ndr_pull_HYPER_T(ndr, t));
973         (*t) *= 10000000;
974         return NT_STATUS_OK;
975 }
976
977 /*
978   push a time_t
979 */
980 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t)
981 {
982         return ndr_push_uint32(ndr, t);
983 }
984
985 /*
986   pull a time_t
987 */
988 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, time_t *t)
989 {
990         uint32_t tt;
991         NDR_CHECK(ndr_pull_uint32(ndr, &tt));
992         *t = tt;
993         return NT_STATUS_OK;
994 }
995
996
997 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
998 {
999         ndr->print(ndr, "%s: struct %s", name, type);
1000 }
1001
1002 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
1003 {
1004         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
1005 }
1006
1007 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
1008 {
1009         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
1010 }
1011
1012 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
1013 {
1014         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1015 }
1016
1017 void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
1018 {
1019         ndr->print(ndr, "%-25s: %d", name, v);
1020 }
1021
1022 void ndr_print_uint64(struct ndr_print *ndr, const char *name, uint64_t v)
1023 {
1024         ndr->print(ndr, "%-25s: 0x%08x%08x (%llu)", name,
1025                    (uint32_t)(v >> 32),
1026                    (uint32_t)(v & 0xFFFFFFFF),
1027                    v);
1028 }
1029
1030 void ndr_print_int64(struct ndr_print *ndr, const char *name, int64_t v)
1031 {
1032         ndr->print(ndr, "%-25s: 0x%08x%08x (%lld)", name, 
1033                    (uint32_t)(v >> 32), 
1034                    (uint32_t)(v & 0xFFFFFFFF),
1035                    v);
1036 }
1037
1038 void ndr_print_HYPER_T(struct ndr_print *ndr, const char *name, HYPER_T v)
1039 {
1040         ndr->print(ndr, "%-25s: 0x%08x%08x", name, (uint32_t)(v >> 32), (uint32_t)(v & 0xFFFFFFFF));
1041 }
1042
1043 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1044 {
1045         if (p) {
1046                 ndr->print(ndr, "%-25s: *", name);
1047         } else {
1048                 ndr->print(ndr, "%-25s: NULL", name);
1049         }
1050 }
1051
1052 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
1053 {
1054         if (s) {
1055                 ndr->print(ndr, "%-25s: '%s'", name, s);
1056         } else {
1057                 ndr->print(ndr, "%-25s: NULL", name);
1058         }
1059 }
1060
1061 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1062 {
1063         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1064 }
1065
1066 void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1067 {
1068         ndr_print_NTTIME(ndr, name, t);
1069 }
1070
1071 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1072 {
1073         if (t == (time_t)-1 || t == 0) {
1074                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1075         } else {
1076                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1077         }
1078 }
1079
1080 void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1081 {
1082         ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1083 }
1084
1085 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1086 {
1087         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1088 }
1089
1090 void ndr_print_array_WERROR(struct ndr_print *ndr, const char *name, 
1091                             const WERROR *data, uint32_t count)
1092 {
1093         int i;
1094
1095         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1096         ndr->depth++;
1097         for (i=0;i<count;i++) {
1098                 char *idx=NULL;
1099                 asprintf(&idx, "[%d]", i);
1100                 if (idx) {
1101                         ndr_print_WERROR(ndr, idx, data[i]);
1102                         free(idx);
1103                 }
1104         }
1105         ndr->depth--;   
1106 }
1107
1108 void ndr_print_array_HYPER_T(struct ndr_print *ndr, const char *name, 
1109                             const HYPER_T *data, uint32_t count)
1110 {
1111         int i;
1112
1113         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1114         ndr->depth++;
1115         for (i=0;i<count;i++) {
1116                 char *idx=NULL;
1117                 asprintf(&idx, "[%d]", i);
1118                 if (idx) {
1119                         ndr_print_HYPER_T(ndr, idx, data[i]);
1120                         free(idx);
1121                 }
1122         }
1123         ndr->depth--;   
1124 }
1125
1126 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
1127                             const uint32_t *data, uint32_t count)
1128 {
1129         int i;
1130
1131         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1132         ndr->depth++;
1133         for (i=0;i<count;i++) {
1134                 char *idx=NULL;
1135                 asprintf(&idx, "[%d]", i);
1136                 if (idx) {
1137                         ndr_print_uint32(ndr, idx, data[i]);
1138                         free(idx);
1139                 }
1140         }
1141         ndr->depth--;   
1142 }
1143
1144 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
1145                             const uint16_t *data, uint32_t count)
1146 {
1147         int i;
1148
1149         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1150         ndr->depth++;
1151         for (i=0;i<count;i++) {
1152                 char *idx=NULL;
1153                 asprintf(&idx, "[%d]", i);
1154                 if (idx) {
1155                         ndr_print_uint16(ndr, idx, data[i]);
1156                         free(idx);
1157                 }
1158         }
1159         ndr->depth--;   
1160 }
1161
1162 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1163                            const uint8_t *data, uint32_t count)
1164 {
1165         int i;
1166
1167         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1168                 char s[1202];
1169                 for (i=0;i<count;i++) {
1170                         snprintf(&s[i*2], 3, "%02x", data[i]);
1171                 }
1172                 s[i*2] = 0;
1173                 ndr->print(ndr, "%-25s: %s", name, s);
1174                 return;
1175         }
1176
1177         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1178         ndr->depth++;
1179         for (i=0;i<count;i++) {
1180                 char *idx=NULL;
1181                 asprintf(&idx, "[%d]", i);
1182                 if (idx) {
1183                         ndr_print_uint8(ndr, idx, data[i]);
1184                         free(idx);
1185                 }
1186         }
1187         ndr->depth--;   
1188 }
1189
1190 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1191 {
1192         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
1193         if (r.length) {
1194                 dump_data(10, r.data, r.length);
1195         }
1196 }
1197
1198
1199 /*
1200   push a DATA_BLOB onto the wire. 
1201 */
1202 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob)
1203 {
1204         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1205                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1206                         blob.length = NDR_ALIGN(ndr, 2);
1207                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1208                         blob.length = NDR_ALIGN(ndr, 4);
1209                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1210                         blob.length = NDR_ALIGN(ndr, 8);
1211                 }
1212                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1213                 data_blob_clear(&blob);
1214         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1215                 NDR_CHECK(ndr_push_uint32(ndr, blob.length));
1216         }
1217         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1218         return NT_STATUS_OK;
1219 }
1220
1221 /*
1222   pull a DATA_BLOB from the wire. 
1223 */
1224 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob)
1225 {
1226         uint32_t length;
1227
1228         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1229                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1230                         length = NDR_ALIGN(ndr, 2);
1231                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1232                         length = NDR_ALIGN(ndr, 4);
1233                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1234                         length = NDR_ALIGN(ndr, 8);
1235                 }
1236                 if (ndr->data_size - ndr->offset < length) {
1237                         length = ndr->data_size - ndr->offset;
1238                 }
1239         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1240                 length = ndr->data_size - ndr->offset;
1241         } else {
1242                 NDR_CHECK(ndr_pull_uint32(ndr, &length));
1243         }
1244         NDR_PULL_NEED_BYTES(ndr, length);
1245         *blob = data_blob_talloc(ndr, ndr->data+ndr->offset, length);
1246         ndr->offset += length;
1247         return NT_STATUS_OK;
1248 }
1249
1250 uint32 ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1251 {
1252         return ret + data->length;
1253 }
1254
1255 uint32 ndr_size_string(int ret, const char * const* string, int flags) 
1256 {
1257         /* FIXME: Is this correct for all strings ? */
1258         if(!(*string)) return ret;
1259         return ret+strlen(*string)+1;
1260 }