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