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 :
26 : const DATA_BLOB data_blob_null = { NULL, 0 };
27 :
28 : /**
29 : * @file
30 : * @brief Manipulation of arbitrary data blobs
31 : **/
32 :
33 : /**
34 : construct a data blob, must be freed with data_blob_free()
35 : you can pass NULL for p and get a blank data blob
36 : **/
37 3212550 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
38 : {
39 3212550 : return data_blob_talloc_named(NULL, p, length, name);
40 : }
41 :
42 : /**
43 : construct a data blob, using supplied TALLOC_CTX
44 : **/
45 556691816 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
46 : {
47 11729363 : DATA_BLOB ret;
48 :
49 556691816 : if (p == NULL && length == 0) {
50 3085554 : ZERO_STRUCT(ret);
51 3085554 : return ret;
52 : }
53 :
54 553606262 : if (p) {
55 411563761 : ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
56 : } else {
57 142042501 : ret.data = talloc_array(mem_ctx, uint8_t, length);
58 : }
59 553606262 : if (ret.data == NULL) {
60 0 : ret.length = 0;
61 0 : return ret;
62 : }
63 553606262 : talloc_set_name_const(ret.data, name);
64 553606262 : ret.length = length;
65 553606262 : return ret;
66 : }
67 :
68 : /**
69 : construct a zero data blob, using supplied TALLOC_CTX.
70 : use this sparingly as it initialises data - better to initialise
71 : yourself if you want specific data in the blob
72 : **/
73 544991 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
74 : {
75 544991 : DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
76 544991 : data_blob_clear(&blob);
77 544991 : return blob;
78 : }
79 :
80 : /**
81 : free a data blob
82 : **/
83 116987713 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
84 : {
85 116987713 : if (d) {
86 116987679 : TALLOC_FREE(d->data);
87 116987679 : d->length = 0;
88 : }
89 116987713 : }
90 :
91 : /**
92 : clear a DATA_BLOB's contents
93 : **/
94 1595383 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
95 : {
96 1595383 : if (d->data) {
97 1147643 : memset_s(d->data, d->length, 0, d->length);
98 : }
99 1595383 : }
100 :
101 : /**
102 : free a data blob and clear its contents
103 : **/
104 733290 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
105 : {
106 733290 : data_blob_clear(d);
107 733290 : data_blob_free(d);
108 733290 : }
109 :
110 :
111 : /**
112 : check if two data blobs are equal
113 : **/
114 18301515 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
115 : {
116 545486 : int ret;
117 18301515 : if (d1->data == NULL && d2->data != NULL) {
118 0 : return -1;
119 : }
120 18301515 : if (d1->data != NULL && d2->data == NULL) {
121 0 : return 1;
122 : }
123 18301515 : if (d1->data == d2->data) {
124 20191 : return d1->length - d2->length;
125 : }
126 18281324 : ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
127 18281324 : if (ret == 0) {
128 : /* Note this ordering is used in conditional aces */
129 7402656 : return d1->length - d2->length;
130 : }
131 10797930 : return ret;
132 : }
133 :
134 : /**
135 : check if two data blobs are equal, where the time taken should not depend on the
136 : contents of either blob.
137 : **/
138 2367 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
139 : {
140 78 : bool ret;
141 2367 : if (d1->data == NULL && d2->data != NULL) {
142 0 : return false;
143 : }
144 2363 : if (d1->data != NULL && d2->data == NULL) {
145 0 : return false;
146 : }
147 2359 : if (d1->length != d2->length) {
148 0 : return false;
149 : }
150 2353 : if (d1->data == d2->data) {
151 0 : return true;
152 : }
153 2348 : ret = mem_equal_const_time(d1->data, d2->data, d1->length);
154 2348 : return ret;
155 : }
156 :
157 : /**
158 : print the data_blob as hex string
159 : **/
160 8677030 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
161 : {
162 218266 : size_t i;
163 218266 : char *hex_string;
164 :
165 8677030 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
166 8677030 : if (!hex_string) {
167 0 : return NULL;
168 : }
169 :
170 : /* this must be lowercase or w2k8 cannot join a samba domain,
171 : as this routine is used to encode extended DNs and windows
172 : only accepts lowercase hexadecimal numbers */
173 155592262 : for (i = 0; i < blob->length; i++)
174 146915232 : slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
175 :
176 8677030 : hex_string[(blob->length*2)] = '\0';
177 8677030 : return hex_string;
178 : }
179 :
180 14323338 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
181 : {
182 21408 : size_t i;
183 21408 : char *hex_string;
184 :
185 14323338 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
186 14323338 : if (!hex_string) {
187 0 : return NULL;
188 : }
189 :
190 431163371 : for (i = 0; i < blob->length; i++)
191 416840033 : slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
192 :
193 14323338 : hex_string[(blob->length*2)] = '\0';
194 14323338 : return hex_string;
195 : }
196 :
197 : /**
198 : useful for constructing data blobs in test suites, while
199 : avoiding const warnings
200 : **/
201 87995177 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
202 : {
203 3408189 : DATA_BLOB blob;
204 87995177 : blob.data = discard_const_p(uint8_t, str);
205 87995177 : blob.length = str ? strlen(str) : 0;
206 87995177 : return blob;
207 : }
208 :
209 : /**
210 : useful for constructing data blobs in test suites, while
211 : avoiding const warnings
212 : **/
213 608349 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
214 : {
215 9228 : DATA_BLOB blob;
216 608349 : blob.data = discard_const_p(uint8_t, str);
217 608349 : blob.length = str ? strlen(str)+1 : 0;
218 608349 : return blob;
219 : }
220 :
221 : /**
222 : * Create a new data blob from const data
223 : */
224 :
225 86717863 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
226 : {
227 1403676 : DATA_BLOB blob;
228 86717863 : blob.data = discard_const_p(uint8_t, p);
229 86717863 : blob.length = length;
230 86717863 : return blob;
231 : }
232 :
233 :
234 : /**
235 : realloc a data_blob
236 : **/
237 4472339 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
238 : {
239 4472339 : uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
240 4472339 : if (tmp == NULL) {
241 0 : return false;
242 : }
243 4472339 : blob->data = tmp;
244 4472339 : blob->length = length;
245 4472339 : return true;
246 : }
247 :
248 :
249 : /**
250 : append some data to a data blob
251 : **/
252 1222754 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
253 : const void *p, size_t length)
254 : {
255 1222754 : size_t old_len = blob->length;
256 1222754 : size_t new_len = old_len + length;
257 :
258 1222754 : if (length == 0) {
259 7573 : return true;
260 : }
261 :
262 1214472 : if (new_len < length || new_len < old_len) {
263 0 : return false;
264 : }
265 :
266 1214472 : if ((const uint8_t *)p + length < (const uint8_t *)p) {
267 0 : return false;
268 : }
269 :
270 1214472 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
271 0 : return false;
272 : }
273 :
274 1214472 : memcpy(blob->data + old_len, p, length);
275 1214472 : return true;
276 : }
277 :
278 : /**
279 : pad the length of a data blob to a multiple of
280 : 'pad'. 'pad' must be a power of two.
281 : **/
282 30492 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
283 : size_t pad)
284 : {
285 30492 : size_t old_len = blob->length;
286 30492 : size_t new_len = (old_len + pad - 1) & ~(pad - 1);
287 :
288 30492 : if (new_len < old_len) {
289 0 : return false;
290 : }
291 :
292 30492 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
293 0 : return false;
294 : }
295 :
296 30492 : memset(blob->data + old_len, 0, new_len - old_len);
297 30492 : return true;
298 : }
|