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 2102366 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
38 : {
39 2102366 : return data_blob_talloc_named(NULL, p, length, name);
40 : }
41 :
42 : /**
43 : construct a data blob, using supplied TALLOC_CTX
44 : **/
45 188105462 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
46 : {
47 : DATA_BLOB ret;
48 :
49 188105462 : if (p == NULL && length == 0) {
50 2108185 : ZERO_STRUCT(ret);
51 2108185 : return ret;
52 : }
53 :
54 185997277 : if (p) {
55 87275062 : ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
56 : } else {
57 98722215 : ret.data = talloc_array(mem_ctx, uint8_t, length);
58 : }
59 185997277 : if (ret.data == NULL) {
60 0 : ret.length = 0;
61 0 : return ret;
62 : }
63 185997277 : talloc_set_name_const(ret.data, name);
64 185997277 : ret.length = length;
65 185997277 : 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 582983 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
74 : {
75 582983 : DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
76 582983 : data_blob_clear(&blob);
77 582983 : return blob;
78 : }
79 :
80 : /**
81 : free a data blob
82 : **/
83 84013274 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
84 : {
85 84013274 : if (d) {
86 84013259 : TALLOC_FREE(d->data);
87 84013259 : d->length = 0;
88 : }
89 84013274 : }
90 :
91 : /**
92 : clear a DATA_BLOB's contents
93 : **/
94 817930 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
95 : {
96 817930 : if (d->data) {
97 792958 : memset_s(d->data, d->length, 0, d->length);
98 : }
99 817930 : }
100 :
101 : /**
102 : free a data blob and clear its contents
103 : **/
104 88535 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
105 : {
106 88535 : data_blob_clear(d);
107 88535 : data_blob_free(d);
108 88535 : }
109 :
110 :
111 : /**
112 : check if two data blobs are equal
113 : **/
114 6091786 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
115 : {
116 : int ret;
117 6091786 : if (d1->data == NULL && d2->data != NULL) {
118 0 : return -1;
119 : }
120 6091786 : if (d1->data != NULL && d2->data == NULL) {
121 0 : return 1;
122 : }
123 6091786 : if (d1->data == d2->data) {
124 14523 : return d1->length - d2->length;
125 : }
126 6077263 : ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
127 6077263 : if (ret == 0) {
128 3380503 : return d1->length - d2->length;
129 : }
130 2696760 : return ret;
131 : }
132 :
133 : /**
134 : check if two data blobs are equal, where the time taken should not depend on the
135 : contents of either blob.
136 : **/
137 1579 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
138 : {
139 : bool ret;
140 1579 : if (d1->data == NULL && d2->data != NULL) {
141 0 : return false;
142 : }
143 1579 : if (d1->data != NULL && d2->data == NULL) {
144 0 : return false;
145 : }
146 1579 : if (d1->length != d2->length) {
147 0 : return false;
148 : }
149 1579 : if (d1->data == d2->data) {
150 0 : return true;
151 : }
152 1579 : ret = mem_equal_const_time(d1->data, d2->data, d1->length);
153 1579 : return ret;
154 : }
155 :
156 : /**
157 : print the data_blob as hex string
158 : **/
159 5943350 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
160 : {
161 : size_t i;
162 : char *hex_string;
163 :
164 5943350 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
165 5943350 : if (!hex_string) {
166 0 : return NULL;
167 : }
168 :
169 : /* this must be lowercase or w2k8 cannot join a samba domain,
170 : as this routine is used to encode extended DNs and windows
171 : only accepts lowercase hexadecimal numbers */
172 104634802 : for (i = 0; i < blob->length; i++)
173 98691452 : slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
174 :
175 5943350 : hex_string[(blob->length*2)] = '\0';
176 5943350 : return hex_string;
177 : }
178 :
179 6024780 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
180 : {
181 : size_t i;
182 : char *hex_string;
183 :
184 6024780 : hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
185 6024780 : if (!hex_string) {
186 0 : return NULL;
187 : }
188 :
189 132778440 : for (i = 0; i < blob->length; i++)
190 126753660 : slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
191 :
192 6024780 : hex_string[(blob->length*2)] = '\0';
193 6024780 : return hex_string;
194 : }
195 :
196 : /**
197 : useful for constructing data blobs in test suites, while
198 : avoiding const warnings
199 : **/
200 47191401 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
201 : {
202 : DATA_BLOB blob;
203 47191401 : blob.data = discard_const_p(uint8_t, str);
204 47191401 : blob.length = str ? strlen(str) : 0;
205 47191401 : return blob;
206 : }
207 :
208 : /**
209 : useful for constructing data blobs in test suites, while
210 : avoiding const warnings
211 : **/
212 62045 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
213 : {
214 : DATA_BLOB blob;
215 62045 : blob.data = discard_const_p(uint8_t, str);
216 62045 : blob.length = str ? strlen(str)+1 : 0;
217 62045 : return blob;
218 : }
219 :
220 : /**
221 : * Create a new data blob from const data
222 : */
223 :
224 22511856 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
225 : {
226 : DATA_BLOB blob;
227 22511856 : blob.data = discard_const_p(uint8_t, p);
228 22511856 : blob.length = length;
229 22511856 : return blob;
230 : }
231 :
232 :
233 : /**
234 : realloc a data_blob
235 : **/
236 2010732 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
237 : {
238 2010732 : uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
239 2010732 : if (tmp == NULL) {
240 0 : return false;
241 : }
242 2010732 : blob->data = tmp;
243 2010732 : blob->length = length;
244 2010732 : return true;
245 : }
246 :
247 :
248 : /**
249 : append some data to a data blob
250 : **/
251 128995 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
252 : const void *p, size_t length)
253 : {
254 128995 : size_t old_len = blob->length;
255 128995 : size_t new_len = old_len + length;
256 :
257 128995 : if (length == 0) {
258 2762 : return true;
259 : }
260 :
261 126233 : if (new_len < length || new_len < old_len) {
262 0 : return false;
263 : }
264 :
265 126233 : if ((const uint8_t *)p + length < (const uint8_t *)p) {
266 0 : return false;
267 : }
268 :
269 126233 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
270 0 : return false;
271 : }
272 :
273 126233 : memcpy(blob->data + old_len, p, length);
274 126233 : return true;
275 : }
276 :
277 : /**
278 : pad the length of a data blob to a multiple of
279 : 'pad'. 'pad' must be a power of two.
280 : **/
281 19010 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
282 : size_t pad)
283 : {
284 19010 : size_t old_len = blob->length;
285 19010 : size_t new_len = (old_len + pad - 1) & ~(pad - 1);
286 :
287 19010 : if (new_len < old_len) {
288 0 : return false;
289 : }
290 :
291 19010 : if (!data_blob_realloc(mem_ctx, blob, new_len)) {
292 0 : return false;
293 : }
294 :
295 19010 : memset(blob->data + old_len, 0, new_len - old_len);
296 19010 : return true;
297 : }
|