Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Easy management of byte-length data
4 : Copyright (C) Andrew Tridgell 2001
5 : Copyright (C) Andrew Bartlett 2001
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "replace.h"
22 : #include "attr.h"
23 : #include "data_blob.h"
24 : #include "lib/util/samba_util.h"
25 : #include "lib/util/tsort.h"
26 :
27 : const DATA_BLOB data_blob_null = { NULL, 0 };
28 :
29 : /**
30 : * @file
31 : * @brief Manipulation of arbitrary data blobs
32 : **/
33 :
34 : /**
35 : construct a data blob, must be freed with data_blob_free()
36 : you can pass NULL for p and get a blank data blob
37 : **/
38 3271255 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
39 : {
40 3271255 : return data_blob_talloc_named(NULL, p, length, name);
41 : }
42 :
43 : /**
44 : construct a data blob, using supplied TALLOC_CTX
45 : **/
46 381703203 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
47 : {
48 5254260 : DATA_BLOB ret;
49 :
50 381703203 : if (p == NULL && length == 0) {
51 3150549 : ZERO_STRUCT(ret);
52 3150549 : return ret;
53 : }
54 :
55 378552654 : if (p) {
56 234645007 : ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
57 : } else {
58 143907647 : ret.data = talloc_array(mem_ctx, uint8_t, length);
59 : }
60 378552654 : if (ret.data == NULL) {
61 0 : ret.length = 0;
62 0 : return ret;
63 : }
64 378552654 : talloc_set_name_const(ret.data, name);
65 378552654 : ret.length = length;
66 378552654 : return ret;
67 : }
68 :
69 : /**
70 : construct a zero data blob, using supplied TALLOC_CTX.
71 : use this sparingly as it initialises data - better to initialise
72 : yourself if you want specific data in the blob
73 : **/
74 547444 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
75 : {
76 547444 : DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
77 547444 : data_blob_clear(&blob);
78 547444 : return blob;
79 : }
80 :
81 : /**
82 : free a data blob
83 : **/
84 118498938 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
85 : {
86 118498938 : if (d) {
87 118498904 : TALLOC_FREE(d->data);
88 118498904 : d->length = 0;
89 : }
90 118498938 : }
91 :
92 : /**
93 : clear a DATA_BLOB's contents
94 : **/
95 1609445 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
96 : {
97 1609445 : if (d->data) {
98 1164504 : memset_s(d->data, d->length, 0, d->length);
99 : }
100 1609445 : }
101 :
102 : /**
103 : free a data blob and clear its contents
104 : **/
105 733335 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
106 : {
107 733335 : data_blob_clear(d);
108 733335 : data_blob_free(d);
109 733335 : }
110 :
111 :
112 : /**
113 : check if two data blobs are equal
114 : **/
115 18400682 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
116 : {
117 545714 : int ret;
118 18400682 : if (d1->data == NULL && d2->data != NULL) {
119 0 : return -1;
120 : }
121 18400682 : if (d1->data != NULL && d2->data == NULL) {
122 0 : return 1;
123 : }
124 18400682 : if (d1->data == d2->data) {
125 19438 : return NUMERIC_CMP(d1->length, d2->length);
126 : }
127 18381244 : ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
128 18381244 : if (ret == 0) {
129 : /* Note this ordering is used in conditional aces */
130 7431344 : return NUMERIC_CMP(d1->length, d2->length);
131 : }
132 10869104 : return ret;
133 : }
134 :
135 : /**
136 : check if two data blobs are equal, where the time taken should not depend on the
137 : contents of either blob.
138 : **/
139 2476 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
140 : {
141 78 : bool ret;
142 2476 : if (d1->data == NULL && d2->data != NULL) {
143 0 : return false;
144 : }
145 2472 : if (d1->data != NULL && d2->data == NULL) {
146 0 : return false;
147 : }
148 2468 : if (d1->length != d2->length) {
149 0 : return false;
150 : }
151 2462 : if (d1->data == d2->data) {
152 0 : return true;
153 : }
154 2457 : ret = mem_equal_const_time(d1->data, d2->data, d1->length);
155 2457 : return ret;
156 : }
157 :
158 : /**
159 : print the data_blob as hex string
160 : **/
161 8744824 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
162 : {
163 218398 : size_t i;
164 218398 : char *hex_string;
165 :
166 8744824 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
167 8744824 : if (!hex_string) {
168 0 : return NULL;
169 : }
170 :
171 : /* this must be lowercase or w2k8 cannot join a samba domain,
172 : as this routine is used to encode extended DNs and windows
173 : only accepts lowercase hexadecimal numbers */
174 156832448 : for (i = 0; i < blob->length; i++)
175 148087624 : slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
176 :
177 8744824 : hex_string[(blob->length*2)] = '\0';
178 8744824 : return hex_string;
179 : }
180 :
181 14708384 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
182 : {
183 22422 : size_t i;
184 22422 : char *hex_string;
185 :
186 14708384 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
187 14708384 : if (!hex_string) {
188 0 : return NULL;
189 : }
190 :
191 439690171 : for (i = 0; i < blob->length; i++)
192 424981787 : slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
193 :
194 14708384 : hex_string[(blob->length*2)] = '\0';
195 14708384 : return hex_string;
196 : }
197 :
198 : /**
199 : useful for constructing data blobs in test suites, while
200 : avoiding const warnings
201 : **/
202 89153801 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
203 : {
204 3409408 : DATA_BLOB blob;
205 89153801 : blob.data = discard_const_p(uint8_t, str);
206 89153801 : blob.length = str ? strlen(str) : 0;
207 89153801 : return blob;
208 : }
209 :
210 : /**
211 : useful for constructing data blobs in test suites, while
212 : avoiding const warnings
213 : **/
214 612233 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
215 : {
216 9228 : DATA_BLOB blob;
217 612233 : blob.data = discard_const_p(uint8_t, str);
218 612233 : blob.length = str ? strlen(str)+1 : 0;
219 612233 : return blob;
220 : }
221 :
222 : /**
223 : * Create a new data blob from const data
224 : */
225 :
226 87199969 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
227 : {
228 1416466 : DATA_BLOB blob;
229 87199969 : blob.data = discard_const_p(uint8_t, p);
230 87199969 : blob.length = length;
231 87199969 : return blob;
232 : }
233 :
234 :
235 : /**
236 : realloc a data_blob
237 : **/
238 4492210 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
239 : {
240 4492210 : uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
241 4492210 : if (tmp == NULL) {
242 0 : return false;
243 : }
244 4492210 : blob->data = tmp;
245 4492210 : blob->length = length;
246 4492210 : return true;
247 : }
248 :
249 :
250 : /**
251 : append some data to a data blob
252 : **/
253 1233499 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
254 : const void *p, size_t length)
255 : {
256 1233499 : size_t old_len = blob->length;
257 1233499 : size_t new_len = old_len + length;
258 :
259 1233499 : if (length == 0) {
260 7610 : return true;
261 : }
262 :
263 1225180 : if (new_len < length || new_len < old_len) {
264 0 : return false;
265 : }
266 :
267 1225180 : if ((const uint8_t *)p + length < (const uint8_t *)p) {
268 0 : return false;
269 : }
270 :
271 1225180 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
272 0 : return false;
273 : }
274 :
275 1225180 : memcpy(blob->data + old_len, p, length);
276 1225180 : return true;
277 : }
278 :
279 : /**
280 : pad the length of a data blob to a multiple of
281 : 'pad'. 'pad' must be a power of two.
282 : **/
283 31067 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
284 : size_t pad)
285 : {
286 31067 : size_t old_len = blob->length;
287 31067 : size_t new_len = (old_len + pad - 1) & ~(pad - 1);
288 :
289 31067 : if (new_len < old_len) {
290 0 : return false;
291 : }
292 :
293 31067 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
294 0 : return false;
295 : }
296 :
297 31067 : memset(blob->data + old_len, 0, new_len - old_len);
298 31067 : return true;
299 : }
|