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