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 3194430 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
38 : {
39 3194430 : return data_blob_talloc_named(NULL, p, length, name);
40 : }
41 :
42 : /**
43 : construct a data blob, using supplied TALLOC_CTX
44 : **/
45 554480109 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
46 : {
47 11701012 : DATA_BLOB ret;
48 :
49 554480109 : if (p == NULL && length == 0) {
50 3071593 : ZERO_STRUCT(ret);
51 3071593 : return ret;
52 : }
53 :
54 551408516 : if (p) {
55 409340920 : ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
56 : } else {
57 142067596 : ret.data = talloc_array(mem_ctx, uint8_t, length);
58 : }
59 551408516 : if (ret.data == NULL) {
60 0 : ret.length = 0;
61 0 : return ret;
62 : }
63 551408516 : talloc_set_name_const(ret.data, name);
64 551408516 : ret.length = length;
65 551408516 : 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 542784 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
74 : {
75 542784 : DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
76 542784 : data_blob_clear(&blob);
77 542784 : return blob;
78 : }
79 :
80 : /**
81 : free a data blob
82 : **/
83 117044153 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
84 : {
85 117044153 : if (d) {
86 117044119 : TALLOC_FREE(d->data);
87 117044119 : d->length = 0;
88 : }
89 117044153 : }
90 :
91 : /**
92 : clear a DATA_BLOB's contents
93 : **/
94 1579472 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
95 : {
96 1579472 : if (d->data) {
97 1140663 : memset_s(d->data, d->length, 0, d->length);
98 : }
99 1579472 : }
100 :
101 : /**
102 : free a data blob and clear its contents
103 : **/
104 723892 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
105 : {
106 723892 : data_blob_clear(d);
107 723892 : data_blob_free(d);
108 723892 : }
109 :
110 :
111 : /**
112 : check if two data blobs are equal
113 : **/
114 18293843 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
115 : {
116 544505 : int ret;
117 18293843 : if (d1->data == NULL && d2->data != NULL) {
118 0 : return -1;
119 : }
120 18293843 : if (d1->data != NULL && d2->data == NULL) {
121 0 : return 1;
122 : }
123 18293843 : if (d1->data == d2->data) {
124 18433 : return d1->length - d2->length;
125 : }
126 18275410 : ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
127 18275410 : if (ret == 0) {
128 : /* Note this ordering is used in conditional aces */
129 7398342 : return d1->length - d2->length;
130 : }
131 10796735 : 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 8690299 : _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 8690299 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
166 8690299 : 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 155835303 : for (i = 0; i < blob->length; i++)
174 147145004 : slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
175 :
176 8690299 : hex_string[(blob->length*2)] = '\0';
177 8690299 : return hex_string;
178 : }
179 :
180 14440097 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
181 : {
182 21608 : size_t i;
183 21608 : char *hex_string;
184 :
185 14440097 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
186 14440097 : if (!hex_string) {
187 0 : return NULL;
188 : }
189 :
190 433096090 : for (i = 0; i < blob->length; i++)
191 418655993 : slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
192 :
193 14440097 : hex_string[(blob->length*2)] = '\0';
194 14440097 : return hex_string;
195 : }
196 :
197 : /**
198 : useful for constructing data blobs in test suites, while
199 : avoiding const warnings
200 : **/
201 88094356 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
202 : {
203 3394106 : DATA_BLOB blob;
204 88094356 : blob.data = discard_const_p(uint8_t, str);
205 88094356 : blob.length = str ? strlen(str) : 0;
206 88094356 : return blob;
207 : }
208 :
209 : /**
210 : useful for constructing data blobs in test suites, while
211 : avoiding const warnings
212 : **/
213 606600 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
214 : {
215 9228 : DATA_BLOB blob;
216 606600 : blob.data = discard_const_p(uint8_t, str);
217 606600 : blob.length = str ? strlen(str)+1 : 0;
218 606600 : return blob;
219 : }
220 :
221 : /**
222 : * Create a new data blob from const data
223 : */
224 :
225 85899143 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
226 : {
227 1393750 : DATA_BLOB blob;
228 85899143 : blob.data = discard_const_p(uint8_t, p);
229 85899143 : blob.length = length;
230 85899143 : return blob;
231 : }
232 :
233 :
234 : /**
235 : realloc a data_blob
236 : **/
237 4472215 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
238 : {
239 4472215 : uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
240 4472215 : if (tmp == NULL) {
241 0 : return false;
242 : }
243 4472215 : blob->data = tmp;
244 4472215 : blob->length = length;
245 4472215 : return true;
246 : }
247 :
248 :
249 : /**
250 : append some data to a data blob
251 : **/
252 1221617 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
253 : const void *p, size_t length)
254 : {
255 1221617 : size_t old_len = blob->length;
256 1221617 : size_t new_len = old_len + length;
257 :
258 1221617 : if (length == 0) {
259 7569 : return true;
260 : }
261 :
262 1213339 : if (new_len < length || new_len < old_len) {
263 0 : return false;
264 : }
265 :
266 1213339 : if ((const uint8_t *)p + length < (const uint8_t *)p) {
267 0 : return false;
268 : }
269 :
270 1213339 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
271 0 : return false;
272 : }
273 :
274 1213339 : memcpy(blob->data + old_len, p, length);
275 1213339 : 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 30226 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
283 : size_t pad)
284 : {
285 30226 : size_t old_len = blob->length;
286 30226 : size_t new_len = (old_len + pad - 1) & ~(pad - 1);
287 :
288 30226 : if (new_len < old_len) {
289 0 : return false;
290 : }
291 :
292 30226 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
293 0 : return false;
294 : }
295 :
296 30226 : memset(blob->data + old_len, 0, new_len - old_len);
297 30226 : return true;
298 : }
|