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