~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source4/librpc/ndr/ndr_string.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
 
 
4
 
   routines for marshalling/unmarshalling string 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 3 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, see <http://www.gnu.org/licenses/>.
20
 
*/
21
 
 
22
 
#include "includes.h"
23
 
#include "librpc/ndr/libndr.h"
24
 
 
25
 
/**
26
 
  pull a general string from the wire
27
 
*/
28
 
_PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
29
 
{
30
 
        char *as=NULL;
31
 
        uint32_t len1, ofs, len2;
32
 
        uint16_t len3;
33
 
        size_t ret;
34
 
        charset_t chset = CH_UTF16;
35
 
        unsigned byte_mul = 2;
36
 
        unsigned flags = ndr->flags;
37
 
        unsigned c_len_term = 0;
38
 
 
39
 
        if (!(ndr_flags & NDR_SCALARS)) {
40
 
                return NDR_ERR_SUCCESS;
41
 
        }
42
 
 
43
 
        if (NDR_BE(ndr)) {
44
 
                chset = CH_UTF16BE;
45
 
        }
46
 
 
47
 
        if (flags & LIBNDR_FLAG_STR_ASCII) {
48
 
                chset = CH_DOS;
49
 
                byte_mul = 1;
50
 
                flags &= ~LIBNDR_FLAG_STR_ASCII;
51
 
        }
52
 
 
53
 
        if (flags & LIBNDR_FLAG_STR_UTF8) {
54
 
                chset = CH_UTF8;
55
 
                byte_mul = 1;
56
 
                flags &= ~LIBNDR_FLAG_STR_UTF8;
57
 
        }
58
 
 
59
 
        flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
60
 
        if (flags & LIBNDR_FLAG_STR_CHARLEN) {
61
 
                c_len_term = 1;
62
 
                flags &= ~LIBNDR_FLAG_STR_CHARLEN;
63
 
        }
64
 
 
65
 
        switch (flags & LIBNDR_STRING_FLAGS) {
66
 
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
67
 
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
68
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
69
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
70
 
                if (ofs != 0) {
71
 
                        return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
72
 
                                              ndr->flags & LIBNDR_STRING_FLAGS);
73
 
                }
74
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
75
 
                if (len2 > len1) {
76
 
                        return ndr_pull_error(ndr, NDR_ERR_STRING, 
77
 
                                              "Bad string lengths len1=%u ofs=%u len2=%u\n", 
78
 
                                              len1, ofs, len2);
79
 
                }
80
 
                NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
81
 
                if (len2 == 0) {
82
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
83
 
                } else {
84
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
85
 
                                                    ndr->iconv_convenience, chset, CH_UNIX, 
86
 
                                                    ndr->data+ndr->offset, 
87
 
                                                    (len2 + c_len_term)*byte_mul,
88
 
                                                    (void **)&as, &ret, false)) {
89
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
90
 
                                                      "Bad character conversion with flags 0x%x", flags);
91
 
                        }
92
 
                }
93
 
                NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
94
 
 
95
 
                if (len1 != len2) {
96
 
                        DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
97
 
                }
98
 
 
99
 
                /* this is a way of detecting if a string is sent with the wrong
100
 
                   termination */
101
 
                if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
102
 
                        if (strlen(as) < (len2 + c_len_term)) {
103
 
                                DEBUG(6,("short string '%s'\n", as));
104
 
                        }
105
 
                } else {
106
 
                        if (strlen(as) == (len2 + c_len_term)) {
107
 
                                DEBUG(6,("long string '%s'\n", as));
108
 
                        }
109
 
                }
110
 
                *s = as;
111
 
                break;
112
 
 
113
 
        case LIBNDR_FLAG_STR_SIZE4:
114
 
        case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
115
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
116
 
                NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
117
 
                if (len1 == 0) {
118
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
119
 
                } else {
120
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
121
 
                                                    ndr->iconv_convenience, 
122
 
                                                    chset, CH_UNIX, 
123
 
                                                    ndr->data+ndr->offset, 
124
 
                                                    (len1 + c_len_term)*byte_mul,
125
 
                                                    (void **)&as, &ret, false)) {
126
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
127
 
                                                      "Bad character conversion with flags 0x%x", flags);
128
 
                        }
129
 
                }
130
 
                NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
131
 
 
132
 
                /* this is a way of detecting if a string is sent with the wrong
133
 
                   termination */
134
 
                if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
135
 
                        if (strlen(as) < (len1 + c_len_term)) {
136
 
                                DEBUG(6,("short string '%s'\n", as));
137
 
                        }
138
 
                } else {
139
 
                        if (strlen(as) == (len1 + c_len_term)) {
140
 
                                DEBUG(6,("long string '%s'\n", as));
141
 
                        }
142
 
                }
143
 
                *s = as;
144
 
                break;
145
 
 
146
 
        case LIBNDR_FLAG_STR_LEN4:
147
 
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
148
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
149
 
                if (ofs != 0) {
150
 
                        return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
151
 
                                              ndr->flags & LIBNDR_STRING_FLAGS);
152
 
                }
153
 
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
154
 
                NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
155
 
                if (len1 == 0) {
156
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
157
 
                } else {
158
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
159
 
                                                    ndr->iconv_convenience, 
160
 
                                                    chset, CH_UNIX, 
161
 
                                                    ndr->data+ndr->offset, 
162
 
                                                    (len1 + c_len_term)*byte_mul,
163
 
                                                    (void **)&as, &ret, false)) {
164
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
165
 
                                                      "Bad character conversion with flags 0x%x", flags);
166
 
                        }
167
 
                }
168
 
                NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
169
 
 
170
 
                /* this is a way of detecting if a string is sent with the wrong
171
 
                   termination */
172
 
                if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
173
 
                        if (strlen(as) < (len1 + c_len_term)) {
174
 
                                DEBUG(6,("short string '%s'\n", as));
175
 
                        }
176
 
                } else {
177
 
                        if (strlen(as) == (len1 + c_len_term)) {
178
 
                                DEBUG(6,("long string '%s'\n", as));
179
 
                        }
180
 
                }
181
 
                *s = as;
182
 
                break;
183
 
 
184
 
 
185
 
        case LIBNDR_FLAG_STR_SIZE2:
186
 
        case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
187
 
                NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
188
 
                NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
189
 
                if (len3 == 0) {
190
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
191
 
                } else {
192
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
193
 
                                                    ndr->iconv_convenience,
194
 
                                                    chset, CH_UNIX, 
195
 
                                                    ndr->data+ndr->offset, 
196
 
                                                    (len3 + c_len_term)*byte_mul,
197
 
                                                    (void **)&as, &ret, false)) {
198
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
199
 
                                                      "Bad character conversion with flags 0x%x", flags);
200
 
                        }
201
 
                }
202
 
                NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
203
 
 
204
 
                /* this is a way of detecting if a string is sent with the wrong
205
 
                   termination */
206
 
                if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
207
 
                        if (strlen(as) < (len3 + c_len_term)) {
208
 
                                DEBUG(6,("short string '%s'\n", as));
209
 
                        }
210
 
                } else {
211
 
                        if (strlen(as) == (len3 + c_len_term)) {
212
 
                                DEBUG(6,("long string '%s'\n", as));
213
 
                        }
214
 
                }
215
 
                *s = as;
216
 
                break;
217
 
 
218
 
        case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
219
 
                NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
220
 
                NDR_PULL_NEED_BYTES(ndr, len3);
221
 
                if (len3 == 0) {
222
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
223
 
                } else {
224
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
225
 
                                                    ndr->iconv_convenience, 
226
 
                                                    chset, CH_UNIX, 
227
 
                                                    ndr->data+ndr->offset, 
228
 
                                                    len3,
229
 
                                                    (void **)&as, &ret, false)) {
230
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
231
 
                                                      "Bad character conversion with flags 0x%x", flags);
232
 
                        }
233
 
                }
234
 
                NDR_CHECK(ndr_pull_advance(ndr, len3));
235
 
                *s = as;
236
 
                break;
237
 
 
238
 
        case LIBNDR_FLAG_STR_NULLTERM:
239
 
                if (byte_mul == 1) {
240
 
                        len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
241
 
                } else {
242
 
                        len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
243
 
                }
244
 
                if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
245
 
                                            ndr->iconv_convenience, chset, CH_UNIX, 
246
 
                                            ndr->data+ndr->offset, 
247
 
                                            len1,
248
 
                                            (void **)&as, &ret, false)) {
249
 
                        return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
250
 
                                              "Bad character conversion with flags 0x%x", flags);
251
 
                }
252
 
                NDR_CHECK(ndr_pull_advance(ndr, len1));
253
 
                *s = as;
254
 
                break;
255
 
 
256
 
        case LIBNDR_FLAG_STR_NOTERM:
257
 
                if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
258
 
                        return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
259
 
                                              ndr->flags & LIBNDR_STRING_FLAGS);
260
 
                }
261
 
 
262
 
                len1 = ndr->data_size - ndr->offset;
263
 
 
264
 
                NDR_PULL_NEED_BYTES(ndr, len1);
265
 
                if (len1 == 0) {
266
 
                        as = talloc_strdup(ndr->current_mem_ctx, "");
267
 
                } else {
268
 
                        if (!convert_string_talloc_convenience(ndr->current_mem_ctx,
269
 
                                                    ndr->iconv_convenience,
270
 
                                                    chset, CH_UNIX, 
271
 
                                                    ndr->data+ndr->offset, 
272
 
                                                    len1,
273
 
                                                    (void **)&as, &ret, false)) {
274
 
                                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
275
 
                                                      "Bad character conversion with flags 0x%x", flags);
276
 
                        }
277
 
                }
278
 
                NDR_CHECK(ndr_pull_advance(ndr, len1));
279
 
 
280
 
                *s = as;
281
 
                break;
282
 
 
283
 
        default:
284
 
                return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
285
 
                                      ndr->flags & LIBNDR_STRING_FLAGS);
286
 
        }
287
 
 
288
 
        return NDR_ERR_SUCCESS;
289
 
}
290
 
 
291
 
 
292
 
/**
293
 
  push a general string onto the wire
294
 
*/
295
 
_PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
296
 
{
297
 
        size_t s_len, c_len, d_len;
298
 
        int chset = CH_UTF16;
299
 
        unsigned flags = ndr->flags;
300
 
        unsigned byte_mul = 2;
301
 
        uint8_t *dest = NULL;
302
 
 
303
 
        if (!(ndr_flags & NDR_SCALARS)) {
304
 
                return NDR_ERR_SUCCESS;
305
 
        }
306
 
 
307
 
        if (NDR_BE(ndr)) {
308
 
                chset = CH_UTF16BE;
309
 
        }
310
 
        
311
 
        s_len = s?strlen(s):0;
312
 
 
313
 
        if (flags & LIBNDR_FLAG_STR_ASCII) {
314
 
                chset = CH_DOS;
315
 
                byte_mul = 1;
316
 
                flags &= ~LIBNDR_FLAG_STR_ASCII;
317
 
        }
318
 
 
319
 
        if (flags & LIBNDR_FLAG_STR_UTF8) {
320
 
                chset = CH_UTF8;
321
 
                byte_mul = 1;
322
 
                flags &= ~LIBNDR_FLAG_STR_UTF8;
323
 
        }
324
 
 
325
 
        flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
326
 
 
327
 
        if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
328
 
                s_len++;
329
 
        }
330
 
        if (!convert_string_talloc_convenience(ndr, ndr->iconv_convenience, CH_UNIX, chset, s, s_len, (void **)&dest, &d_len, false)) {
331
 
                return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
332
 
                                      "Bad character push conversion with flags 0x%x", flags);
333
 
        }
334
 
 
335
 
        if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
336
 
                c_len = d_len;
337
 
                flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
338
 
        } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
339
 
                c_len = (d_len / byte_mul)-1;
340
 
                flags &= ~LIBNDR_FLAG_STR_CHARLEN;
341
 
        } else {
342
 
                c_len = d_len / byte_mul;
343
 
        }
344
 
 
345
 
        switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
346
 
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
347
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
348
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
349
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
350
 
                NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
351
 
                break;
352
 
 
353
 
        case LIBNDR_FLAG_STR_LEN4:
354
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
355
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
356
 
                NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
357
 
                break;
358
 
 
359
 
        case LIBNDR_FLAG_STR_SIZE4:
360
 
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
361
 
                NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
362
 
                break;
363
 
 
364
 
        case LIBNDR_FLAG_STR_SIZE2:
365
 
                NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
366
 
                NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
367
 
                break;
368
 
 
369
 
        case LIBNDR_FLAG_STR_NULLTERM:
370
 
                NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
371
 
                break;
372
 
 
373
 
        default:
374
 
                if (ndr->flags & LIBNDR_FLAG_REMAINING) {
375
 
                        NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
376
 
                        break;          
377
 
                }
378
 
 
379
 
                return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
380
 
                                      ndr->flags & LIBNDR_STRING_FLAGS);
381
 
        }
382
 
 
383
 
        talloc_free(dest);
384
 
 
385
 
        return NDR_ERR_SUCCESS;
386
 
}
387
 
 
388
 
/**
389
 
  push a general string onto the wire
390
 
*/
391
 
_PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
392
 
{
393
 
        size_t c_len;
394
 
        unsigned flags = ndr->flags;
395
 
        unsigned byte_mul = 2;
396
 
        unsigned c_len_term = 1;
397
 
 
398
 
        c_len = s?strlen_m(s):0;
399
 
 
400
 
        if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
401
 
                byte_mul = 1;
402
 
        }
403
 
 
404
 
        if (flags & LIBNDR_FLAG_STR_NOTERM) {
405
 
                c_len_term = 0;
406
 
        }
407
 
 
408
 
        c_len = c_len + c_len_term;
409
 
 
410
 
        if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
411
 
                c_len = c_len * byte_mul;
412
 
        }
413
 
 
414
 
        return c_len;
415
 
}
416
 
 
417
 
_PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
418
 
{
419
 
        if (s) {
420
 
                ndr->print(ndr, "%-25s: '%s'", name, s);
421
 
        } else {
422
 
                ndr->print(ndr, "%-25s: NULL", name);
423
 
        }
424
 
}
425
 
 
426
 
_PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
427
 
{
428
 
        /* FIXME: Is this correct for all strings ? */
429
 
        if(!(*string)) return ret;
430
 
        return ret+strlen(*string)+1;
431
 
}
432
 
 
433
 
/**
434
 
  pull a general string array from the wire
435
 
*/
436
 
_PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
437
 
{
438
 
        const char **a = NULL;
439
 
        uint32_t count;
440
 
        unsigned flags = ndr->flags;
441
 
        unsigned saved_flags = ndr->flags;
442
 
 
443
 
        if (!(ndr_flags & NDR_SCALARS)) {
444
 
                return NDR_ERR_SUCCESS;
445
 
        }
446
 
 
447
 
        switch (flags & LIBNDR_STRING_FLAGS) {
448
 
        case LIBNDR_FLAG_STR_NULLTERM:
449
 
                /* 
450
 
                 * here the strings are null terminated
451
 
                 * but also the array is null terminated
452
 
                 */
453
 
                for (count = 0;; count++) {
454
 
                        TALLOC_CTX *tmp_ctx;
455
 
                        const char *s = NULL;
456
 
                        a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
457
 
                        NDR_ERR_HAVE_NO_MEMORY(a);
458
 
                        a[count]   = NULL;
459
 
                        a[count+1]   = NULL;
460
 
 
461
 
                        tmp_ctx = ndr->current_mem_ctx;
462
 
                        ndr->current_mem_ctx = a;
463
 
                        NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
464
 
                        ndr->current_mem_ctx = tmp_ctx;
465
 
                        if (strcmp("", s)==0) {
466
 
                                a[count] = NULL;
467
 
                                break;
468
 
                        } else {
469
 
                                a[count] = s;
470
 
                        }
471
 
                }
472
 
 
473
 
                *_a =a;
474
 
                break;
475
 
 
476
 
        case LIBNDR_FLAG_STR_NOTERM:
477
 
                if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
478
 
                        return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
479
 
                                              ndr->flags & LIBNDR_STRING_FLAGS);
480
 
                }
481
 
                /*
482
 
                 * here the strings are not null terminated
483
 
                 * but serarated by a null terminator
484
 
                 *
485
 
                 * which means the same as:
486
 
                 * very string is null terminated exept the last
487
 
                 * string is terminated by the end of the buffer
488
 
                 *
489
 
                 * as LIBNDR_FLAG_STR_NULLTERM also end at the end
490
 
                 * of the buffer, we can pull each string with this flag
491
 
                 */
492
 
                ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
493
 
                ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
494
 
 
495
 
                for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
496
 
                        TALLOC_CTX *tmp_ctx;
497
 
                        const char *s = NULL;
498
 
                        a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
499
 
                        NDR_ERR_HAVE_NO_MEMORY(a);
500
 
                        a[count]   = NULL;
501
 
                        a[count+1]   = NULL;
502
 
 
503
 
                        tmp_ctx = ndr->current_mem_ctx;
504
 
                        ndr->current_mem_ctx = a;
505
 
                        NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
506
 
                        ndr->current_mem_ctx = tmp_ctx;
507
 
                        a[count] = s;
508
 
                }
509
 
 
510
 
                *_a =a;
511
 
                break;
512
 
 
513
 
        default:
514
 
                return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
515
 
                                      ndr->flags & LIBNDR_STRING_FLAGS);
516
 
        }
517
 
 
518
 
        ndr->flags = saved_flags;
519
 
        return NDR_ERR_SUCCESS;
520
 
}
521
 
 
522
 
/**
523
 
  push a general string array onto the wire
524
 
*/
525
 
_PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
526
 
{
527
 
        uint32_t count;
528
 
        unsigned flags = ndr->flags;
529
 
        unsigned saved_flags = ndr->flags;
530
 
 
531
 
        if (!(ndr_flags & NDR_SCALARS)) {
532
 
                return NDR_ERR_SUCCESS;
533
 
        }
534
 
 
535
 
        switch (flags & LIBNDR_STRING_FLAGS) {
536
 
        case LIBNDR_FLAG_STR_NULLTERM:
537
 
                for (count = 0; a && a[count]; count++) {
538
 
                        NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
539
 
                }
540
 
 
541
 
                NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
542
 
                break;
543
 
 
544
 
        case LIBNDR_FLAG_STR_NOTERM:
545
 
                if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
546
 
                        return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
547
 
                                              ndr->flags & LIBNDR_STRING_FLAGS);
548
 
                }
549
 
 
550
 
                for (count = 0; a && a[count]; count++) {
551
 
                        if (count > 0) {
552
 
                                ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
553
 
                                ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
554
 
                                NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
555
 
                                ndr->flags = saved_flags;
556
 
                        }
557
 
                        NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
558
 
                }
559
 
 
560
 
                break;
561
 
 
562
 
        default:
563
 
                return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
564
 
                                      ndr->flags & LIBNDR_STRING_FLAGS);
565
 
        }
566
 
        
567
 
        ndr->flags = saved_flags;
568
 
        return NDR_ERR_SUCCESS;
569
 
}
570
 
 
571
 
_PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
572
 
{
573
 
        uint32_t count;
574
 
        uint32_t i;
575
 
 
576
 
        for (count = 0; a && a[count]; count++) {}
577
 
 
578
 
        ndr->print(ndr, "%s: ARRAY(%d)", name, count);
579
 
        ndr->depth++;
580
 
        for (i=0;i<count;i++) {
581
 
                char *idx=NULL;
582
 
                if (asprintf(&idx, "[%d]", i) != -1) {
583
 
                        ndr_print_string(ndr, idx, a[i]);
584
 
                        free(idx);
585
 
                }
586
 
        }
587
 
        ndr->depth--;
588
 
}
589
 
 
590
 
_PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags)
591
 
{
592
 
        uint32_t i;
593
 
        size_t size = 0;
594
 
 
595
 
        switch (flags & LIBNDR_STRING_FLAGS) {
596
 
        case LIBNDR_FLAG_STR_NULLTERM:
597
 
                for (i = 0; i < count; i++) {
598
 
                        size += strlen_m_term(a[i]);
599
 
                }
600
 
                break;
601
 
        case LIBNDR_FLAG_STR_NOTERM:
602
 
                for (i = 0; i < count; i++) {
603
 
                        size += strlen_m(a[i]);
604
 
                }
605
 
                break;
606
 
        default:
607
 
                return 0;
608
 
        }
609
 
 
610
 
        return size;
611
 
}
612
 
 
613
 
/**
614
 
 * Return number of elements in a string including the last (zeroed) element 
615
 
 */
616
 
_PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
617
 
{
618
 
        uint32_t i;
619
 
        uint8_t zero[4] = {0,0,0,0};
620
 
        const char *var = (const char *)_var;
621
 
 
622
 
        for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
623
 
 
624
 
        return i+1;
625
 
}
626
 
 
627
 
_PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
628
 
{
629
 
        uint32_t i;
630
 
        uint32_t save_offset;
631
 
 
632
 
        save_offset = ndr->offset;
633
 
        ndr_pull_advance(ndr, (count - 1) * element_size);
634
 
        NDR_PULL_NEED_BYTES(ndr, element_size);
635
 
 
636
 
        for (i = 0; i < element_size; i++) {
637
 
                 if (ndr->data[ndr->offset+i] != 0) {
638
 
                        ndr->offset = save_offset;
639
 
 
640
 
                        return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
641
 
                 }
642
 
        }
643
 
 
644
 
        ndr->offset = save_offset;
645
 
 
646
 
        return NDR_ERR_SUCCESS;
647
 
}
648
 
 
649
 
_PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
650
 
{
651
 
        size_t ret;
652
 
        if (length == 0) {
653
 
                *var = talloc_strdup(ndr->current_mem_ctx, "");
654
 
                return NDR_ERR_SUCCESS;
655
 
        }
656
 
 
657
 
        if (NDR_BE(ndr) && chset == CH_UTF16) {
658
 
                chset = CH_UTF16BE;
659
 
        }
660
 
 
661
 
        NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
662
 
 
663
 
        if (!convert_string_talloc_convenience(ndr->current_mem_ctx, 
664
 
                                    ndr->iconv_convenience,
665
 
                                    chset, CH_UNIX, 
666
 
                                    ndr->data+ndr->offset, 
667
 
                                    length*byte_mul,
668
 
                                    discard_const_p(void *, var), &ret, false)) {
669
 
                return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
670
 
                                      "Bad character conversion");
671
 
        }
672
 
        NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
673
 
 
674
 
        return NDR_ERR_SUCCESS;
675
 
}
676
 
 
677
 
_PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
678
 
{
679
 
        size_t ret, required;
680
 
 
681
 
        if (NDR_BE(ndr) && chset == CH_UTF16) {
682
 
                chset = CH_UTF16BE;
683
 
        }
684
 
 
685
 
        required = byte_mul * length;
686
 
        
687
 
        NDR_PUSH_NEED_BYTES(ndr, required);
688
 
        if (!convert_string_convenience(ndr->iconv_convenience, CH_UNIX, chset, 
689
 
                             var, strlen(var),
690
 
                             ndr->data+ndr->offset, required, &ret, false)) {
691
 
                return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
692
 
                                      "Bad character conversion");
693
 
        }
694
 
 
695
 
        /* Make sure the remaining part of the string is filled with zeroes */
696
 
        if (ret < required) {
697
 
                memset(ndr->data+ndr->offset+ret, 0, required-ret);
698
 
        }
699
 
 
700
 
        ndr->offset += required;
701
 
 
702
 
        return NDR_ERR_SUCCESS;
703
 
}
704
 
 
705
 
/* Return number of elements in a string in the specified charset */
706
 
_PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
707
 
{
708
 
        /* FIXME: Treat special chars special here, taking chset into account */
709
 
        /* Also include 0 byte */
710
 
        return strlen((const char *)var)+1;
711
 
}