tests/krb5: Add tests for account salt calculation
[Samba.git] / source4 / libcli / raw / raweas.c
blob2f551b0e6fca7c2362ff10dca0bfc367d27d9e19
1 /*
2 Unix SMB/CIFS implementation.
3 parsing of EA (extended attribute) lists
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
25 work out how many bytes on the wire a ea list will consume.
26 This assumes the names are strict ascii, which should be a
27 reasonable assumption
29 size_t ea_list_size(unsigned int num_eas, struct ea_struct *eas)
31 unsigned int total = 4;
32 int i;
33 for (i=0;i<num_eas;i++) {
34 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
36 return total;
40 work out how many bytes on the wire a ea name list will consume.
42 static unsigned int ea_name_list_size(unsigned int num_names, struct ea_name *eas)
44 unsigned int total = 4;
45 int i;
46 for (i=0;i<num_names;i++) {
47 total += 1 + strlen(eas[i].name.s) + 1;
49 return total;
53 work out how many bytes on the wire a chained ea list will consume.
54 This assumes the names are strict ascii, which should be a
55 reasonable assumption
57 size_t ea_list_size_chained(unsigned int num_eas, struct ea_struct *eas, unsigned alignment)
59 unsigned int total = 0;
60 int i;
61 for (i=0;i<num_eas;i++) {
62 unsigned int len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
63 len = (len + (alignment-1)) & ~(alignment-1);
64 total += len;
66 return total;
70 put a ea_list into a pre-allocated buffer - buffer must be at least
71 of size ea_list_size()
73 void ea_put_list(uint8_t *data, unsigned int num_eas, struct ea_struct *eas)
75 int i;
76 uint32_t ea_size;
78 ea_size = ea_list_size(num_eas, eas);
80 SIVAL(data, 0, ea_size);
81 data += 4;
83 for (i=0;i<num_eas;i++) {
84 unsigned int nlen = strlen(eas[i].name.s);
85 SCVAL(data, 0, eas[i].flags);
86 SCVAL(data, 1, nlen);
87 SSVAL(data, 2, eas[i].value.length);
88 memcpy(data+4, eas[i].name.s, nlen+1);
89 if (eas[i].value.length > 0) {
90 memcpy(data + 4 + nlen + 1,
91 eas[i].value.data,
92 eas[i].value.length);
94 data += 4+nlen+1+eas[i].value.length;
100 put a chained ea_list into a pre-allocated buffer - buffer must be
101 at least of size ea_list_size()
103 void ea_put_list_chained(uint8_t *data, unsigned int num_eas, struct ea_struct *eas,
104 unsigned alignment)
106 int i;
108 for (i=0;i<num_eas;i++) {
109 unsigned int nlen = strlen(eas[i].name.s);
110 uint32_t len = 8+nlen+1+eas[i].value.length;
111 unsigned int pad = ((len + (alignment-1)) & ~(alignment-1)) - len;
112 if (i == num_eas-1) {
113 SIVAL(data, 0, 0);
114 } else {
115 SIVAL(data, 0, len+pad);
117 SCVAL(data, 4, eas[i].flags);
118 SCVAL(data, 5, nlen);
119 SSVAL(data, 6, eas[i].value.length);
120 memcpy(data+8, eas[i].name.s, nlen+1);
121 memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
122 memset(data+len, 0, pad);
123 data += len + pad;
129 pull a ea_struct from a buffer. Return the number of bytes consumed
131 unsigned int ea_pull_struct(const DATA_BLOB *blob,
132 TALLOC_CTX *mem_ctx,
133 struct ea_struct *ea)
135 uint8_t nlen;
136 uint16_t vlen;
138 ZERO_STRUCTP(ea);
140 if (blob->length < 6) {
141 return 0;
144 ea->flags = CVAL(blob->data, 0);
145 nlen = CVAL(blob->data, 1);
146 vlen = SVAL(blob->data, 2);
148 if (nlen+1+vlen > blob->length-4) {
149 return 0;
152 ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+4), nlen);
153 ea->name.private_length = nlen;
154 ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
155 if (!ea->value.data) return 0;
156 if (vlen) {
157 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
159 ea->value.data[vlen] = 0;
160 ea->value.length--;
162 return 4 + nlen+1 + vlen;
167 pull a ea_list from a buffer
169 NTSTATUS ea_pull_list(const DATA_BLOB *blob,
170 TALLOC_CTX *mem_ctx,
171 unsigned int *num_eas, struct ea_struct **eas)
173 int n;
174 uint32_t ea_size, ofs;
176 if (blob->length < 4) {
177 return NT_STATUS_INFO_LENGTH_MISMATCH;
180 ea_size = IVAL(blob->data, 0);
181 if (ea_size > blob->length) {
182 return NT_STATUS_INVALID_PARAMETER;
185 ofs = 4;
186 n = 0;
187 *num_eas = 0;
188 *eas = NULL;
190 while (ofs < ea_size) {
191 unsigned int len;
192 DATA_BLOB blob2;
194 blob2.data = blob->data + ofs;
195 blob2.length = ea_size - ofs;
197 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
198 if (! *eas) return NT_STATUS_NO_MEMORY;
200 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
201 if (len == 0) {
202 return NT_STATUS_INVALID_PARAMETER;
205 ofs += len;
206 n++;
209 *num_eas = n;
211 return NT_STATUS_OK;
216 pull a chained ea_list from a buffer
218 NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob,
219 TALLOC_CTX *mem_ctx,
220 unsigned int *num_eas, struct ea_struct **eas)
222 int n;
223 uint32_t ofs;
225 if (blob->length < 4) {
226 return NT_STATUS_INFO_LENGTH_MISMATCH;
229 ofs = 0;
230 n = 0;
231 *num_eas = 0;
232 *eas = NULL;
234 while (ofs < blob->length) {
235 unsigned int len;
236 DATA_BLOB blob2;
237 uint32_t next_ofs = IVAL(blob->data, ofs);
239 blob2.data = blob->data + ofs + 4;
240 blob2.length = blob->length - (ofs + 4);
242 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
243 if (! *eas) return NT_STATUS_NO_MEMORY;
245 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
246 if (len == 0) {
247 return NT_STATUS_INVALID_PARAMETER;
250 if (ofs + next_ofs < ofs) {
251 return NT_STATUS_INVALID_PARAMETER;
254 ofs += next_ofs;
255 if (ofs+4 > blob->length || ofs+4 < ofs) {
256 return NT_STATUS_INVALID_PARAMETER;
258 n++;
259 if (next_ofs == 0) break;
262 *num_eas = n;
264 return NT_STATUS_OK;
269 pull a ea_name from a buffer. Return the number of bytes consumed
271 static unsigned int ea_pull_name(const DATA_BLOB *blob,
272 TALLOC_CTX *mem_ctx,
273 struct ea_name *ea)
275 uint8_t nlen;
277 if (blob->length < 2) {
278 return 0;
281 nlen = CVAL(blob->data, 0);
283 if (nlen+2 > blob->length) {
284 return 0;
287 ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+1), nlen);
288 ea->name.private_length = nlen;
290 return nlen+2;
295 pull a ea_name list from a buffer
297 NTSTATUS ea_pull_name_list(const DATA_BLOB *blob,
298 TALLOC_CTX *mem_ctx,
299 unsigned int *num_names, struct ea_name **ea_names)
301 int n;
302 uint32_t ea_size, ofs;
304 if (blob->length < 4) {
305 return NT_STATUS_INFO_LENGTH_MISMATCH;
308 ea_size = IVAL(blob->data, 0);
309 if (ea_size > blob->length) {
310 return NT_STATUS_INVALID_PARAMETER;
313 ofs = 4;
314 n = 0;
315 *num_names = 0;
316 *ea_names = NULL;
318 while (ofs < ea_size) {
319 unsigned int len;
320 DATA_BLOB blob2;
322 blob2.data = blob->data + ofs;
323 blob2.length = ea_size - ofs;
325 *ea_names = talloc_realloc(mem_ctx, *ea_names, struct ea_name, n+1);
326 if (! *ea_names) return NT_STATUS_NO_MEMORY;
328 len = ea_pull_name(&blob2, mem_ctx, &(*ea_names)[n]);
329 if (len == 0) {
330 return NT_STATUS_INVALID_PARAMETER;
333 ofs += len;
334 n++;
337 *num_names = n;
339 return NT_STATUS_OK;
344 put a ea_name list into a data blob
346 bool ea_push_name_list(TALLOC_CTX *mem_ctx,
347 DATA_BLOB *data, unsigned int num_names, struct ea_name *eas)
349 int i;
350 uint32_t ea_size;
351 uint32_t off;
353 ea_size = ea_name_list_size(num_names, eas);
355 *data = data_blob_talloc(mem_ctx, NULL, ea_size);
356 if (data->data == NULL) {
357 return false;
360 SIVAL(data->data, 0, ea_size);
361 off = 4;
363 for (i=0;i<num_names;i++) {
364 unsigned int nlen = strlen(eas[i].name.s);
365 SCVAL(data->data, off, nlen);
366 memcpy(data->data+off+1, eas[i].name.s, nlen+1);
367 off += 1+nlen+1;
370 return true;