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 3274131 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
39 : {
40 3274131 : return data_blob_talloc_named(NULL, p, length, name);
41 : }
42 :
43 : /**
44 : construct a data blob, using supplied TALLOC_CTX
45 : **/
46 384155419 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
47 : {
48 5262560 : DATA_BLOB ret;
49 :
50 384155419 : if (p == NULL && length == 0) {
51 3150835 : ZERO_STRUCT(ret);
52 3150835 : return ret;
53 : }
54 :
55 381004584 : if (p) {
56 236289132 : ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
57 : } else {
58 144715452 : ret.data = talloc_array(mem_ctx, uint8_t, length);
59 : }
60 381004584 : if (ret.data == NULL) {
61 0 : ret.length = 0;
62 0 : return ret;
63 : }
64 381004584 : talloc_set_name_const(ret.data, name);
65 381004584 : ret.length = length;
66 381004584 : 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 553407 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
75 : {
76 553407 : DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
77 553407 : data_blob_clear(&blob);
78 553407 : return blob;
79 : }
80 :
81 : /**
82 : free a data blob
83 : **/
84 119277858 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
85 : {
86 119277858 : if (d) {
87 119277824 : TALLOC_FREE(d->data);
88 119277824 : d->length = 0;
89 : }
90 119277858 : }
91 :
92 : /**
93 : clear a DATA_BLOB's contents
94 : **/
95 1598865 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
96 : {
97 1598865 : if (d->data) {
98 1159476 : memset_s(d->data, d->length, 0, d->length);
99 : }
100 1598865 : }
101 :
102 : /**
103 : free a data blob and clear its contents
104 : **/
105 728091 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
106 : {
107 728091 : data_blob_clear(d);
108 728091 : data_blob_free(d);
109 728091 : }
110 :
111 :
112 : /**
113 : check if two data blobs are equal
114 : **/
115 18494955 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
116 : {
117 546602 : int ret;
118 18494955 : if (d1->data == NULL && d2->data != NULL) {
119 0 : return -1;
120 : }
121 18494955 : if (d1->data != NULL && d2->data == NULL) {
122 0 : return 1;
123 : }
124 18494955 : if (d1->data == d2->data) {
125 14499 : return NUMERIC_CMP(d1->length, d2->length);
126 : }
127 18480456 : ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
128 18480456 : if (ret == 0) {
129 : /* Note this ordering is used in conditional aces */
130 7460710 : return NUMERIC_CMP(d1->length, d2->length);
131 : }
132 10938221 : 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 2485 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
140 : {
141 78 : bool ret;
142 2485 : if (d1->data == NULL && d2->data != NULL) {
143 0 : return false;
144 : }
145 2481 : if (d1->data != NULL && d2->data == NULL) {
146 0 : return false;
147 : }
148 2477 : if (d1->length != d2->length) {
149 0 : return false;
150 : }
151 2471 : if (d1->data == d2->data) {
152 0 : return true;
153 : }
154 2466 : ret = mem_equal_const_time(d1->data, d2->data, d1->length);
155 2466 : return ret;
156 : }
157 :
158 : /**
159 : print the data_blob as hex string
160 : **/
161 8775598 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
162 : {
163 218426 : size_t i;
164 218426 : char *hex_string;
165 :
166 8775598 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
167 8775598 : 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 157243438 : for (i = 0; i < blob->length; i++)
175 148467840 : slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
176 :
177 8775598 : hex_string[(blob->length*2)] = '\0';
178 8775598 : return hex_string;
179 : }
180 :
181 15009067 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
182 : {
183 22198 : size_t i;
184 22198 : char *hex_string;
185 :
186 15009067 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
187 15009067 : if (!hex_string) {
188 0 : return NULL;
189 : }
190 :
191 445700566 : for (i = 0; i < blob->length; i++)
192 430691499 : slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
193 :
194 15009067 : hex_string[(blob->length*2)] = '\0';
195 15009067 : return hex_string;
196 : }
197 :
198 : /**
199 : useful for constructing data blobs in test suites, while
200 : avoiding const warnings
201 : **/
202 89475355 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
203 : {
204 3424352 : DATA_BLOB blob;
205 89475355 : blob.data = discard_const_p(uint8_t, str);
206 89475355 : blob.length = str ? strlen(str) : 0;
207 89475355 : return blob;
208 : }
209 :
210 : /**
211 : useful for constructing data blobs in test suites, while
212 : avoiding const warnings
213 : **/
214 621679 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
215 : {
216 9488 : DATA_BLOB blob;
217 621679 : blob.data = discard_const_p(uint8_t, str);
218 621679 : blob.length = str ? strlen(str)+1 : 0;
219 621679 : return blob;
220 : }
221 :
222 : /**
223 : * Create a new data blob from const data
224 : */
225 :
226 87309960 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
227 : {
228 1408440 : DATA_BLOB blob;
229 87309960 : blob.data = discard_const_p(uint8_t, p);
230 87309960 : blob.length = length;
231 87309960 : return blob;
232 : }
233 :
234 :
235 : /**
236 : realloc a data_blob
237 : **/
238 4509248 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
239 : {
240 4509248 : uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
241 4509248 : if (tmp == NULL) {
242 0 : return false;
243 : }
244 4509248 : blob->data = tmp;
245 4509248 : blob->length = length;
246 4509248 : return true;
247 : }
248 :
249 :
250 : /**
251 : append some data to a data blob
252 : **/
253 1246601 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
254 : const void *p, size_t length)
255 : {
256 1246601 : size_t old_len = blob->length;
257 1246601 : size_t new_len = old_len + length;
258 :
259 1246601 : if (length == 0) {
260 7680 : return true;
261 : }
262 :
263 1238192 : if (new_len < length || new_len < old_len) {
264 0 : return false;
265 : }
266 :
267 1238192 : if ((const uint8_t *)p + length < (const uint8_t *)p) {
268 0 : return false;
269 : }
270 :
271 1238192 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
272 0 : return false;
273 : }
274 :
275 1238192 : memcpy(blob->data + old_len, p, length);
276 1238192 : 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 30423 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
284 : size_t pad)
285 : {
286 30423 : size_t old_len = blob->length;
287 30423 : size_t new_len = (old_len + pad - 1) & ~(pad - 1);
288 :
289 30423 : if (new_len < old_len) {
290 0 : return false;
291 : }
292 :
293 30423 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
294 0 : return false;
295 : }
296 :
297 30423 : memset(blob->data + old_len, 0, new_len - old_len);
298 30423 : return true;
299 : }
|