Line | Count | Source |
1 | | /* |
2 | | * XML Security Library (http://www.aleksey.com/xmlsec). |
3 | | * |
4 | | * |
5 | | * This is free software; see the Copyright file in the source |
6 | | * distribution for precise wording. |
7 | | * |
8 | | * Copyright (C) 2002-2024 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. |
9 | | */ |
10 | | /** |
11 | | * SECTION:buffer |
12 | | * @Short_description:Binary memory buffer functions. |
13 | | * @Stability: Stable |
14 | | * |
15 | | */ |
16 | | |
17 | | #include "globals.h" |
18 | | |
19 | | #include <stdlib.h> |
20 | | #include <string.h> |
21 | | #include <ctype.h> |
22 | | |
23 | | #include <libxml/tree.h> |
24 | | |
25 | | #include <xmlsec/xmlsec.h> |
26 | | #include <xmlsec/xmltree.h> |
27 | | #include <xmlsec/base64.h> |
28 | | #include <xmlsec/buffer.h> |
29 | | #include <xmlsec/errors.h> |
30 | | |
31 | | #include "cast_helpers.h" |
32 | | |
33 | | /***************************************************************************** |
34 | | * |
35 | | * xmlSecBuffer |
36 | | * |
37 | | ****************************************************************************/ |
38 | | static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble; |
39 | | static xmlSecSize gInitialSize = 1024; |
40 | | |
41 | | /** |
42 | | * xmlSecBufferSetDefaultAllocMode: |
43 | | * @defAllocMode: the new default buffer allocation mode. |
44 | | * @defInitialSize: the new default buffer minimal intial size. |
45 | | * |
46 | | * Sets new global default allocation mode and minimal intial size. |
47 | | */ |
48 | | void |
49 | 0 | xmlSecBufferSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) { |
50 | 0 | xmlSecAssert(defInitialSize > 0); |
51 | |
|
52 | 0 | gAllocMode = defAllocMode; |
53 | 0 | gInitialSize = defInitialSize; |
54 | 0 | } |
55 | | |
56 | | /** |
57 | | * xmlSecBufferCreate: |
58 | | * @size: the intial size. |
59 | | * |
60 | | * Allocates and initializes new memory buffer with given size. |
61 | | * Caller is responsible for calling #xmlSecBufferDestroy function |
62 | | * to free the buffer. |
63 | | * |
64 | | * Returns: pointer to newly allocated buffer or NULL if an error occurs. |
65 | | */ |
66 | | xmlSecBufferPtr |
67 | 18.9k | xmlSecBufferCreate(xmlSecSize size) { |
68 | 18.9k | xmlSecBufferPtr buf; |
69 | 18.9k | int ret; |
70 | | |
71 | 18.9k | buf = (xmlSecBufferPtr)xmlMalloc(sizeof(xmlSecBuffer)); |
72 | 18.9k | if(buf == NULL) { |
73 | 0 | xmlSecMallocError(sizeof(xmlSecBuffer), NULL); |
74 | 0 | return(NULL); |
75 | 0 | } |
76 | | |
77 | 18.9k | ret = xmlSecBufferInitialize(buf, size); |
78 | 18.9k | if(ret < 0) { |
79 | 0 | xmlSecInternalError2("xmlSecBufferInitialize", NULL, "size=" XMLSEC_SIZE_FMT, size); |
80 | 0 | xmlSecBufferDestroy(buf); |
81 | 0 | return(NULL); |
82 | 0 | } |
83 | 18.9k | return(buf); |
84 | 18.9k | } |
85 | | |
86 | | /** |
87 | | * xmlSecBufferDestroy: |
88 | | * @buf: the pointer to buffer object. |
89 | | * |
90 | | * Destroys buffer object created with #xmlSecBufferCreate function. |
91 | | */ |
92 | | void |
93 | 18.9k | xmlSecBufferDestroy(xmlSecBufferPtr buf) { |
94 | 18.9k | xmlSecAssert(buf != NULL); |
95 | | |
96 | 18.9k | xmlSecBufferFinalize(buf); |
97 | 18.9k | xmlFree(buf); |
98 | 18.9k | } |
99 | | |
100 | | /** |
101 | | * xmlSecBufferInitialize: |
102 | | * @buf: the pointer to buffer object. |
103 | | * @size: the initial buffer size. |
104 | | * |
105 | | * Initializes buffer object @buf. Caller is responsible for calling |
106 | | * #xmlSecBufferFinalize function to free allocated resources. |
107 | | * |
108 | | * Returns: 0 on success or a negative value if an error occurs. |
109 | | */ |
110 | | int |
111 | 18.9k | xmlSecBufferInitialize(xmlSecBufferPtr buf, xmlSecSize size) { |
112 | 18.9k | xmlSecAssert2(buf != NULL, -1); |
113 | | |
114 | 18.9k | buf->data = NULL; |
115 | 18.9k | buf->size = buf->maxSize = 0; |
116 | 18.9k | buf->allocMode = gAllocMode; |
117 | | |
118 | 18.9k | return(xmlSecBufferSetMaxSize(buf, size)); |
119 | 18.9k | } |
120 | | |
121 | | /** |
122 | | * xmlSecBufferFinalize: |
123 | | * @buf: the pointer to buffer object. |
124 | | * |
125 | | * Frees allocated resource for a buffer initialized with #xmlSecBufferInitialize |
126 | | * function. |
127 | | */ |
128 | | void |
129 | 18.9k | xmlSecBufferFinalize(xmlSecBufferPtr buf) { |
130 | 18.9k | xmlSecAssert(buf != NULL); |
131 | | |
132 | 18.9k | xmlSecBufferEmpty(buf); |
133 | | |
134 | 18.9k | if(buf->data != 0) { |
135 | 18.9k | xmlFree(buf->data); |
136 | 18.9k | } |
137 | 18.9k | buf->data = NULL; |
138 | 18.9k | buf->size = buf->maxSize = 0; |
139 | 18.9k | } |
140 | | |
141 | | /** |
142 | | * xmlSecBufferEmpty: |
143 | | * @buf: the pointer to buffer object. |
144 | | * |
145 | | * Empties the buffer. |
146 | | */ |
147 | | void |
148 | 37.9k | xmlSecBufferEmpty(xmlSecBufferPtr buf) { |
149 | 37.9k | xmlSecAssert(buf != NULL); |
150 | | |
151 | 37.9k | if(buf->data != 0) { |
152 | 37.9k | xmlSecAssert(buf->maxSize > 0); |
153 | 37.9k | memset(buf->data, 0, buf->maxSize); |
154 | 37.9k | } |
155 | 37.9k | buf->size = 0; |
156 | 37.9k | } |
157 | | |
158 | | /** |
159 | | * xmlSecBufferIsEmpty: |
160 | | * @buf: the pointer to buffer object. |
161 | | * |
162 | | * Checks if the @buf is empty (@buf is null or @buf's data is null or @buf's size is zero). |
163 | | * |
164 | | * Returns: 1 if buffer is empty or 0 otherwise. |
165 | | */ |
166 | | int |
167 | 0 | xmlSecBufferIsEmpty(xmlSecBufferPtr buf) { |
168 | 0 | return (((buf == NULL) || (buf->data == NULL) || (buf->size <= 0)) ? 1 : 0); |
169 | 0 | } |
170 | | |
171 | | /** |
172 | | * xmlSecBufferGetData: |
173 | | * @buf: the pointer to buffer object. |
174 | | * |
175 | | * Gets pointer to buffer's data. |
176 | | * |
177 | | * Returns: pointer to buffer's data. |
178 | | */ |
179 | | xmlSecByte* |
180 | 18.9k | xmlSecBufferGetData(xmlSecBufferPtr buf) { |
181 | 18.9k | xmlSecAssert2(buf != NULL, NULL); |
182 | | |
183 | 18.9k | return(buf->data); |
184 | 18.9k | } |
185 | | |
186 | | /** |
187 | | * xmlSecBufferSetData: |
188 | | * @buf: the pointer to buffer object. |
189 | | * @data: the data. |
190 | | * @size: the data size. |
191 | | * |
192 | | * Sets the value of the buffer to @data. |
193 | | * |
194 | | * Returns: 0 on success or a negative value if an error occurs. |
195 | | */ |
196 | | int |
197 | 18.9k | xmlSecBufferSetData(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) { |
198 | 18.9k | int ret; |
199 | | |
200 | 18.9k | xmlSecAssert2(buf != NULL, -1); |
201 | | |
202 | 18.9k | xmlSecBufferEmpty(buf); |
203 | 18.9k | if(size > 0) { |
204 | 18.9k | xmlSecAssert2(data != NULL, -1); |
205 | | |
206 | 18.9k | ret = xmlSecBufferSetMaxSize(buf, size); |
207 | 18.9k | if(ret < 0) { |
208 | 0 | xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, "size=" XMLSEC_SIZE_FMT, size); |
209 | 0 | return(-1); |
210 | 0 | } |
211 | | |
212 | 18.9k | memcpy(buf->data, data, size); |
213 | 18.9k | } |
214 | | |
215 | 18.9k | buf->size = size; |
216 | 18.9k | return(0); |
217 | 18.9k | } |
218 | | |
219 | | /** |
220 | | * xmlSecBufferGetSize: |
221 | | * @buf: the pointer to buffer object. |
222 | | * |
223 | | * Gets the current buffer data size. |
224 | | * |
225 | | * Returns: the current data size. |
226 | | */ |
227 | | xmlSecSize |
228 | 18.9k | xmlSecBufferGetSize(xmlSecBufferPtr buf) { |
229 | 18.9k | xmlSecAssert2(buf != NULL, 0); |
230 | | |
231 | 18.9k | return(buf->size); |
232 | 18.9k | } |
233 | | |
234 | | /** |
235 | | * xmlSecBufferSetSize: |
236 | | * @buf: the pointer to buffer object. |
237 | | * @size: the new data size. |
238 | | * |
239 | | * Sets new buffer data size. If necessary, buffer grows to |
240 | | * have at least @size bytes. |
241 | | * |
242 | | * Returns: 0 on success or a negative value if an error occurs. |
243 | | */ |
244 | | int |
245 | 0 | xmlSecBufferSetSize(xmlSecBufferPtr buf, xmlSecSize size) { |
246 | 0 | int ret; |
247 | |
|
248 | 0 | xmlSecAssert2(buf != NULL, -1); |
249 | |
|
250 | 0 | ret = xmlSecBufferSetMaxSize(buf, size); |
251 | 0 | if(ret < 0) { |
252 | 0 | xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, "size=" XMLSEC_SIZE_FMT, size); |
253 | 0 | return(-1); |
254 | 0 | } |
255 | | |
256 | | |
257 | 0 | buf->size = size; |
258 | 0 | return(0); |
259 | 0 | } |
260 | | |
261 | | /** |
262 | | * xmlSecBufferGetMaxSize: |
263 | | * @buf: the pointer to buffer object. |
264 | | * |
265 | | * Gets the maximum (allocated) buffer size. |
266 | | * |
267 | | * Returns: the maximum (allocated) buffer size. |
268 | | */ |
269 | | xmlSecSize |
270 | 0 | xmlSecBufferGetMaxSize(xmlSecBufferPtr buf) { |
271 | 0 | xmlSecAssert2(buf != NULL, 0); |
272 | |
|
273 | 0 | return(buf->maxSize); |
274 | 0 | } |
275 | | |
276 | | /** |
277 | | * xmlSecBufferSetMaxSize: |
278 | | * @buf: the pointer to buffer object. |
279 | | * @size: the new maximum size. |
280 | | * |
281 | | * Sets new buffer maximum size. If necessary, buffer grows to |
282 | | * have at least @size bytes. |
283 | | * |
284 | | * Returns: 0 on success or a negative value if an error occurs. |
285 | | */ |
286 | | int |
287 | 37.9k | xmlSecBufferSetMaxSize(xmlSecBufferPtr buf, xmlSecSize size) { |
288 | 37.9k | xmlSecByte* newData; |
289 | 37.9k | xmlSecSize newSize = 0; |
290 | | |
291 | 37.9k | xmlSecAssert2(buf != NULL, -1); |
292 | 37.9k | if(size <= buf->maxSize) { |
293 | 18.9k | return(0); |
294 | 18.9k | } |
295 | | |
296 | 18.9k | switch(buf->allocMode) { |
297 | 0 | case xmlSecAllocModeExact: |
298 | 0 | newSize = size + 8; |
299 | 0 | break; |
300 | 18.9k | case xmlSecAllocModeDouble: |
301 | 18.9k | newSize = 2 * size + 32; |
302 | 18.9k | break; |
303 | 18.9k | } |
304 | | |
305 | 18.9k | if(newSize < gInitialSize) { |
306 | 16.5k | newSize = gInitialSize; |
307 | 16.5k | } |
308 | | |
309 | | |
310 | 18.9k | if(buf->data != NULL) { |
311 | 0 | newData = (xmlSecByte*)xmlRealloc(buf->data, newSize); |
312 | 18.9k | } else { |
313 | 18.9k | newData = (xmlSecByte*)xmlMalloc(newSize); |
314 | 18.9k | } |
315 | 18.9k | if(newData == NULL) { |
316 | 0 | xmlSecMallocError(newSize, NULL); |
317 | 0 | return(-1); |
318 | 0 | } |
319 | | |
320 | 18.9k | buf->data = newData; |
321 | 18.9k | buf->maxSize = newSize; |
322 | | |
323 | 18.9k | if(buf->size < buf->maxSize) { |
324 | 18.9k | xmlSecAssert2(buf->data != NULL, -1); |
325 | 18.9k | memset(buf->data + buf->size, 0, buf->maxSize - buf->size); |
326 | 18.9k | } |
327 | | |
328 | 18.9k | return(0); |
329 | 18.9k | } |
330 | | |
331 | 0 | #define SWAP(type, a, b) do { type tmp = (a); (a) = (b); (b) = tmp; } while (0) |
332 | | |
333 | | /** |
334 | | * xmlSecBufferSwap: |
335 | | * @buf1: the pointer to the first buffer object. |
336 | | * @buf2: the pointer to the second buffer object. |
337 | | * |
338 | | * Swaps the content of the two buffers. |
339 | | */ |
340 | | void |
341 | 0 | xmlSecBufferSwap(xmlSecBufferPtr buf1, xmlSecBufferPtr buf2) { |
342 | 0 | xmlSecAssert(buf1 != NULL); |
343 | 0 | xmlSecAssert(buf2 != NULL); |
344 | |
|
345 | 0 | SWAP(xmlSecByte*, buf1->data, buf2->data); |
346 | 0 | SWAP(xmlSecSize, buf1->size, buf2->size); |
347 | 0 | SWAP(xmlSecSize, buf1->maxSize, buf2->maxSize); |
348 | 0 | SWAP(xmlSecAllocMode, buf1->allocMode, buf2->allocMode); |
349 | 0 | } |
350 | | |
351 | | /** |
352 | | * xmlSecBufferAppend: |
353 | | * @buf: the pointer to buffer object. |
354 | | * @data: the data. |
355 | | * @size: the data size. |
356 | | * |
357 | | * Appends the @data after the current data stored in the buffer. |
358 | | * |
359 | | * Returns: 0 on success or a negative value if an error occurs. |
360 | | */ |
361 | | int |
362 | 0 | xmlSecBufferAppend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) { |
363 | 0 | int ret; |
364 | |
|
365 | 0 | xmlSecAssert2(buf != NULL, -1); |
366 | |
|
367 | 0 | if(size > 0) { |
368 | 0 | xmlSecAssert2(data != NULL, -1); |
369 | |
|
370 | 0 | ret = xmlSecBufferSetMaxSize(buf, buf->size + size); |
371 | 0 | if(ret < 0) { |
372 | 0 | xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, |
373 | 0 | "size=" XMLSEC_SIZE_FMT, (buf->size + size)); |
374 | 0 | return(-1); |
375 | 0 | } |
376 | | |
377 | 0 | memcpy(buf->data + buf->size, data, size); |
378 | 0 | buf->size += size; |
379 | 0 | } |
380 | | |
381 | 0 | return(0); |
382 | 0 | } |
383 | | |
384 | | /** |
385 | | * xmlSecBufferPrepend: |
386 | | * @buf: the pointer to buffer object. |
387 | | * @data: the data. |
388 | | * @size: the data size. |
389 | | * |
390 | | * Prepends the @data before the current data stored in the buffer. |
391 | | * |
392 | | * Returns: 0 on success or a negative value if an error occurs. |
393 | | */ |
394 | | int |
395 | 0 | xmlSecBufferPrepend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) { |
396 | 0 | int ret; |
397 | |
|
398 | 0 | xmlSecAssert2(buf != NULL, -1); |
399 | |
|
400 | 0 | if(size > 0) { |
401 | 0 | xmlSecAssert2(data != NULL, -1); |
402 | |
|
403 | 0 | ret = xmlSecBufferSetMaxSize(buf, buf->size + size); |
404 | 0 | if(ret < 0) { |
405 | 0 | xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, |
406 | 0 | "size=" XMLSEC_SIZE_FMT, (buf->size + size)); |
407 | 0 | return(-1); |
408 | 0 | } |
409 | | |
410 | 0 | memmove(buf->data + size, buf->data, buf->size); |
411 | 0 | memcpy(buf->data, data, size); |
412 | 0 | buf->size += size; |
413 | 0 | } |
414 | | |
415 | 0 | return(0); |
416 | 0 | } |
417 | | |
418 | | /** |
419 | | * xmlSecBufferRemoveHead: |
420 | | * @buf: the pointer to buffer object. |
421 | | * @size: the number of bytes to be removed. |
422 | | * |
423 | | * Removes @size bytes from the beginning of the current buffer. |
424 | | * |
425 | | * Returns: 0 on success or a negative value if an error occurs. |
426 | | */ |
427 | | int |
428 | 0 | xmlSecBufferRemoveHead(xmlSecBufferPtr buf, xmlSecSize size) { |
429 | 0 | xmlSecAssert2(buf != NULL, -1); |
430 | |
|
431 | 0 | if(size < buf->size) { |
432 | 0 | xmlSecAssert2(buf->data != NULL, -1); |
433 | |
|
434 | 0 | buf->size -= size; |
435 | 0 | memmove(buf->data, buf->data + size, buf->size); |
436 | 0 | } else { |
437 | 0 | buf->size = 0; |
438 | 0 | } |
439 | 0 | if(buf->size < buf->maxSize) { |
440 | 0 | xmlSecAssert2(buf->data != NULL, -1); |
441 | 0 | memset(buf->data + buf->size, 0, buf->maxSize - buf->size); |
442 | 0 | } |
443 | 0 | return(0); |
444 | 0 | } |
445 | | |
446 | | /** |
447 | | * xmlSecBufferRemoveTail: |
448 | | * @buf: the pointer to buffer object. |
449 | | * @size: the number of bytes to be removed. |
450 | | * |
451 | | * Removes @size bytes from the end of current buffer. |
452 | | * |
453 | | * Returns: 0 on success or a negative value if an error occurs. |
454 | | */ |
455 | | int |
456 | 0 | xmlSecBufferRemoveTail(xmlSecBufferPtr buf, xmlSecSize size) { |
457 | 0 | xmlSecAssert2(buf != NULL, -1); |
458 | |
|
459 | 0 | if(size < buf->size) { |
460 | 0 | buf->size -= size; |
461 | 0 | } else { |
462 | 0 | buf->size = 0; |
463 | 0 | } |
464 | 0 | if(buf->size < buf->maxSize) { |
465 | 0 | xmlSecAssert2(buf->data != NULL, -1); |
466 | 0 | memset(buf->data + buf->size, 0, buf->maxSize - buf->size); |
467 | 0 | } |
468 | 0 | return(0); |
469 | 0 | } |
470 | | |
471 | | /** |
472 | | * xmlSecBufferReverse: |
473 | | * @buf: the pointer to buffer object. |
474 | | * |
475 | | * Reverses order of bytes in the buffer @buf. |
476 | | * |
477 | | * Returns: 0 on success or a negative value if an error occurs. |
478 | | */ |
479 | | int |
480 | 0 | xmlSecBufferReverse(xmlSecBufferPtr buf) { |
481 | 0 | xmlSecByte* pp; |
482 | 0 | xmlSecByte* qq; |
483 | 0 | xmlSecSize size; |
484 | 0 | xmlSecByte ch; |
485 | |
|
486 | 0 | xmlSecAssert2(buf != NULL, -1); |
487 | | |
488 | | /* trivial case */ |
489 | 0 | size = xmlSecBufferGetSize(buf); |
490 | 0 | if (size <= 1) { |
491 | 0 | return(0); |
492 | 0 | } |
493 | | |
494 | 0 | pp = xmlSecBufferGetData(buf); |
495 | 0 | xmlSecAssert2(pp != NULL, -1); |
496 | |
|
497 | 0 | for (qq = pp + size - 1; pp < qq; ++pp, --qq) { |
498 | 0 | ch = *(pp); |
499 | 0 | *(pp) = *(qq); |
500 | 0 | *(qq) = ch; |
501 | 0 | } |
502 | |
|
503 | 0 | return(0); |
504 | 0 | } |
505 | | |
506 | | |
507 | | /** |
508 | | * xmlSecBufferReadFile: |
509 | | * @buf: the pointer to buffer object. |
510 | | * @filename: the filename. |
511 | | * |
512 | | * Reads the content of the file @filename in the buffer. |
513 | | * |
514 | | * Returns: 0 on success or a negative value if an error occurs. |
515 | | */ |
516 | | int |
517 | 0 | xmlSecBufferReadFile(xmlSecBufferPtr buf, const char* filename) { |
518 | 0 | xmlSecByte buffer[1024]; |
519 | 0 | FILE* f = NULL; |
520 | 0 | xmlSecSize size; |
521 | 0 | size_t len; |
522 | 0 | int ret; |
523 | 0 | int res = -1; |
524 | |
|
525 | 0 | xmlSecAssert2(buf != NULL, -1); |
526 | 0 | xmlSecAssert2(filename != NULL, -1); |
527 | |
|
528 | 0 | #ifndef _MSC_VER |
529 | 0 | f = fopen(filename, "rb"); |
530 | | #else |
531 | | fopen_s(&f, filename, "rb"); |
532 | | #endif /* _MSC_VER */ |
533 | 0 | if(f == NULL) { |
534 | 0 | xmlSecIOError("fopen", filename, NULL); |
535 | 0 | goto done; |
536 | 0 | } |
537 | | |
538 | 0 | while(!feof(f)) { |
539 | 0 | len = fread(buffer, 1, sizeof(buffer), f); |
540 | 0 | if(ferror(f)) { |
541 | 0 | xmlSecIOError("fread", filename, NULL); |
542 | 0 | goto done; |
543 | 0 | } |
544 | | |
545 | 0 | XMLSEC_SAFE_CAST_SIZE_T_TO_SIZE(len, size, goto done, NULL); |
546 | 0 | ret = xmlSecBufferAppend(buf, buffer, size); |
547 | 0 | if(ret < 0) { |
548 | 0 | xmlSecInternalError2("xmlSecBufferAppend", NULL, "size=" XMLSEC_SIZE_T_FMT, len); |
549 | 0 | goto done; |
550 | 0 | } |
551 | 0 | } |
552 | | |
553 | | /* success */ |
554 | 0 | res = 0; |
555 | |
|
556 | 0 | done: |
557 | 0 | if(f != NULL) { |
558 | 0 | fclose(f); |
559 | 0 | } |
560 | 0 | return(res); |
561 | 0 | } |
562 | | |
563 | | /** |
564 | | * xmlSecBufferBase64NodeContentRead: |
565 | | * @buf: the pointer to buffer object. |
566 | | * @node: the pointer to node. |
567 | | * |
568 | | * Reads the content of the @node, base64 decodes it and stores the |
569 | | * result in the buffer. |
570 | | * |
571 | | * Returns: 0 on success or a negative value if an error occurs. |
572 | | */ |
573 | | int |
574 | 0 | xmlSecBufferBase64NodeContentRead(xmlSecBufferPtr buf, xmlNodePtr node) { |
575 | 0 | xmlChar* content = NULL; |
576 | 0 | xmlSecSize outWritten; |
577 | 0 | int ret; |
578 | 0 | int res = -1; |
579 | |
|
580 | 0 | xmlSecAssert2(buf != NULL, -1); |
581 | 0 | xmlSecAssert2(node != NULL, -1); |
582 | |
|
583 | 0 | content = xmlSecGetNodeContentAndTrim(node); |
584 | 0 | if(content == NULL) { |
585 | 0 | xmlSecInvalidNodeContentError(node, NULL, "empty"); |
586 | 0 | goto done; |
587 | 0 | } |
588 | | |
589 | | /* base64 decode size is less than input size */ |
590 | 0 | ret = xmlSecBufferSetMaxSize(buf, xmlSecStrlen(content)); |
591 | 0 | if(ret < 0) { |
592 | 0 | xmlSecInternalError("xmlSecBufferSetMaxSize", NULL); |
593 | 0 | goto done; |
594 | 0 | } |
595 | | |
596 | 0 | ret = xmlSecBase64Decode_ex(content, xmlSecBufferGetData(buf), |
597 | 0 | xmlSecBufferGetMaxSize(buf), &outWritten); |
598 | 0 | if(ret < 0) { |
599 | 0 | xmlSecInternalError("xmlSecBase64Decode_ex", NULL); |
600 | 0 | goto done; |
601 | 0 | } |
602 | | |
603 | 0 | ret = xmlSecBufferSetSize(buf, outWritten); |
604 | 0 | if(ret < 0) { |
605 | 0 | xmlSecInternalError2("xmlSecBufferSetSize", NULL, |
606 | 0 | "size=" XMLSEC_SIZE_FMT, outWritten); |
607 | 0 | goto done; |
608 | 0 | } |
609 | | |
610 | | /* success */ |
611 | 0 | res = 0; |
612 | |
|
613 | 0 | done: |
614 | 0 | if(content != NULL) { |
615 | 0 | xmlFree(content); |
616 | 0 | } |
617 | 0 | return(res); |
618 | 0 | } |
619 | | |
620 | | /** |
621 | | * xmlSecBufferBase64NodeContentWrite: |
622 | | * @buf: the pointer to buffer object. |
623 | | * @node: the pointer to a node. |
624 | | * @columns: the max line size for base64 encoded data. |
625 | | * |
626 | | * Sets the content of the @node to the base64 encoded buffer data. |
627 | | * |
628 | | * Returns: 0 on success or a negative value if an error occurs. |
629 | | */ |
630 | | int |
631 | 0 | xmlSecBufferBase64NodeContentWrite(xmlSecBufferPtr buf, xmlNodePtr node, int columns) { |
632 | 0 | xmlChar* content; |
633 | |
|
634 | 0 | xmlSecAssert2(buf != NULL, -1); |
635 | 0 | xmlSecAssert2(node != NULL, -1); |
636 | |
|
637 | 0 | content = xmlSecBase64Encode(xmlSecBufferGetData(buf), xmlSecBufferGetSize(buf), columns); |
638 | 0 | if(content == NULL) { |
639 | 0 | xmlSecInternalError("xmlSecBase64Encode", NULL); |
640 | 0 | return(-1); |
641 | 0 | } |
642 | | |
643 | 0 | xmlNodeAddContent(node, content); |
644 | 0 | xmlFree(content); |
645 | |
|
646 | 0 | return(0); |
647 | 0 | } |
648 | | |
649 | | |
650 | | /** |
651 | | * xmlSecBufferHexRead: |
652 | | * @buf: the pointer to buffer object. |
653 | | * @hexStr: the hex string. |
654 | | * |
655 | | * Reads content of hex encoded @hexStr into @buf. |
656 | | * |
657 | | * Returns: 0 on success or a negative value if an error occurs. |
658 | | */ |
659 | | int |
660 | 0 | xmlSecBufferHexRead(xmlSecBufferPtr buf, const xmlChar* hexStr) { |
661 | 0 | xmlSecSize hexStrSize, bufSize; |
662 | 0 | xmlSecByte * data; |
663 | 0 | xmlChar ch1, ch2; |
664 | 0 | int ret; |
665 | |
|
666 | 0 | xmlSecAssert2(buf != NULL, -1); |
667 | 0 | xmlSecAssert2(hexStr != NULL, -1); |
668 | | |
669 | | /* trivial case */ |
670 | 0 | hexStrSize = xmlSecStrlen(hexStr); |
671 | 0 | if(hexStrSize <= 0) { |
672 | 0 | xmlSecBufferEmpty(buf); |
673 | 0 | return(0); |
674 | 0 | } |
675 | | |
676 | | /* we expect each byte to be represented by 2 chars */ |
677 | 0 | if((hexStrSize % 2) != 0) { |
678 | 0 | xmlSecInvalidSizeDataError("hexStrSize", hexStrSize, "even", NULL); |
679 | 0 | return(-1); |
680 | 0 | } |
681 | 0 | bufSize = hexStrSize / 2; |
682 | |
|
683 | 0 | ret = xmlSecBufferSetSize(buf, bufSize); |
684 | 0 | if(ret < 0) { |
685 | 0 | xmlSecInternalError2("xmlSecBufferSetSize", NULL, |
686 | 0 | "bufSize=" XMLSEC_SIZE_FMT, bufSize); |
687 | 0 | return (-1); |
688 | 0 | } |
689 | | |
690 | 0 | data = xmlSecBufferGetData(buf); |
691 | 0 | xmlSecAssert2(data != NULL, -1); |
692 | |
|
693 | 0 | for( ; (*hexStr) != '\0'; ++data) { |
694 | 0 | ch1 = *(hexStr++); |
695 | 0 | ch2 = *(hexStr++); |
696 | 0 | if(!xmlSecIsHex(ch1) || !xmlSecIsHex(ch2)) { |
697 | 0 | xmlSecInvalidDataError("Unexpected character (not hex)", NULL); |
698 | 0 | return (-1); |
699 | 0 | } |
700 | 0 | (*data) = xmlSecFromHex2(ch1, ch2); |
701 | 0 | } |
702 | | |
703 | | /* sucess */ |
704 | 0 | return(0); |
705 | 0 | } |
706 | | |
707 | | /************************************************************************ |
708 | | * |
709 | | * IO buffer |
710 | | * |
711 | | ************************************************************************/ |
712 | | static int xmlSecBufferIOWrite (xmlSecBufferPtr buf, |
713 | | const xmlSecByte *data, |
714 | | int len); |
715 | | static int xmlSecBufferIOClose (xmlSecBufferPtr buf); |
716 | | |
717 | | /** |
718 | | * xmlSecBufferCreateOutputBuffer: |
719 | | * @buf: the pointer to buffer. |
720 | | * |
721 | | * Creates new LibXML output buffer to store data in the @buf. Caller is |
722 | | * responsible for destroying @buf when processing is done. |
723 | | * |
724 | | * Returns: pointer to newly allocated output buffer or NULL if an error |
725 | | * occurs. |
726 | | */ |
727 | | xmlOutputBufferPtr |
728 | 0 | xmlSecBufferCreateOutputBuffer(xmlSecBufferPtr buf) { |
729 | 0 | return(xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecBufferIOWrite, |
730 | 0 | (xmlOutputCloseCallback)xmlSecBufferIOClose, |
731 | 0 | buf, |
732 | 0 | NULL)); |
733 | 0 | } |
734 | | |
735 | | static int |
736 | 0 | xmlSecBufferIOWrite(xmlSecBufferPtr buf, const xmlSecByte *data, int len) { |
737 | 0 | xmlSecSize size; |
738 | 0 | int ret; |
739 | |
|
740 | 0 | xmlSecAssert2(buf != NULL, -1); |
741 | 0 | xmlSecAssert2(data != NULL, -1); |
742 | 0 | xmlSecAssert2(len >= 0, -1); |
743 | |
|
744 | 0 | XMLSEC_SAFE_CAST_INT_TO_SIZE(len, size, return(-1), NULL); |
745 | 0 | ret = xmlSecBufferAppend(buf, data, size); |
746 | 0 | if(ret < 0) { |
747 | 0 | xmlSecInternalError2("xmlSecBufferAppend", NULL, "size=" XMLSEC_SIZE_FMT, size); |
748 | 0 | return(-1); |
749 | 0 | } |
750 | | /* we appended the whole input buffer */ |
751 | 0 | return(len); |
752 | 0 | } |
753 | | |
754 | | static int |
755 | 0 | xmlSecBufferIOClose(xmlSecBufferPtr buf) { |
756 | 0 | xmlSecAssert2(buf != NULL, -1); |
757 | | |
758 | | /* just do nothing */ |
759 | 0 | return(0); |
760 | 0 | } |