1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * XSECSafeBuffer := a class for storing expanding amounts of information.
24  *
25  * Author(s): Berin Lautenbach
26  *
27  * $Id: XSECSafeBuffer.cpp 1833341 2018-06-11 16:25:41Z scantor $
28  *
29  */
30 
31 #define __STDC_LIMIT_MACROS
32 
33 // XSEC includes
34 
35 #include <xsec/utils/XSECSafeBuffer.hpp>
36 #include <xsec/framework/XSECError.hpp>
37 #include <xsec/transformers/TXFMBase.hpp>
38 
39 #include "XSECDOMUtils.hpp"
40 
41 #include <xercesc/util/XMLUniDefs.hpp>
42 
43 XSEC_USING_XERCES(XMLString);
44 
45 // Standard includes
46 
47 #include <stdlib.h>
48 #include <string.h>
49 
50 size_t safeBuffer::size_XMLCh;
51 
52 #if defined (_MSC_VER)
53 #pragma warning(disable: 4311)
54 #endif
55 
checkAndExpand(XMLSize_t size)56 void safeBuffer::checkAndExpand(XMLSize_t size) {
57 
58 	// For a given size, check it will fit (with one byte spare)
59 	// and expand if necessary
60 
61 	if (bufferSize >= 2 && size < bufferSize - 2) {
62 		return;
63 	}
64 
65 	if (size > XERCES_SIZE_MAX - DEFAULT_SAFE_BUFFER_SIZE) {
66 		/* We've got a string that's too big to deal with */
67 		throw XSECException(XSECException::SafeBufferError,
68 			"Buffer has grown too large");
69 	}
70 
71 	// Resize and add 1K for further growth
72 	XMLSize_t newBufferSize = size + DEFAULT_SAFE_BUFFER_SIZE;
73 
74 	unsigned char * newBuffer = new unsigned char[newBufferSize];
75 	if (newBuffer == NULL)
76 	{
77 		/* Ran out of memory */
78 		throw XSECException(XSECException::MemoryAllocationFail,
79 			"Error allocating memory for Buffer");
80 	}
81 
82 	memset((void *) newBuffer, 0, newBufferSize);
83 	memcpy(newBuffer, buffer, bufferSize);
84 
85 	// If we are sensitive, clean the old buffer
86 	if (m_isSensitive == true)
87 		cleanseBuffer();
88 
89 	// clean up
90 	bufferSize = newBufferSize;
91 	delete[] buffer;
92 	buffer = newBuffer;
93 }
94 
checkBufferType(bufferType bt) const95 void safeBuffer::checkBufferType(bufferType bt) const {
96 
97 	if (bt != m_bufferType) {
98 
99 		throw XSECException(XSECException::SafeBufferError,
100 			"Attempt to perform an operation on a buffer of incorrect type");
101 	}
102 
103 }
104 
105 
setBufferType(bufferType bt)106 void safeBuffer::setBufferType(bufferType bt) {
107 
108 	m_bufferType = bt;
109 
110 }
111 
resize(XMLSize_t sz)112 void safeBuffer::resize(XMLSize_t sz) {
113 
114 	checkAndExpand(sz);
115 
116 }
117 
safeBuffer(XMLSize_t initialSize)118 safeBuffer::safeBuffer(XMLSize_t initialSize) {
119 
120 	// Initialise the buffer with a set size string
121 
122 	bufferSize = initialSize;
123 	buffer = new unsigned char[initialSize];
124 	memset((void *) buffer, 0, bufferSize);
125 	mp_XMLCh = NULL;
126 	m_bufferType = BUFFER_UNKNOWN;
127 	m_isSensitive = false;
128 
129 }
130 
safeBuffer()131 safeBuffer::safeBuffer() {
132 
133 	bufferSize = DEFAULT_SAFE_BUFFER_SIZE;
134 	buffer = new unsigned char[bufferSize];
135 	memset((void *) buffer, 0, bufferSize);
136 	mp_XMLCh = NULL;
137 	m_bufferType = BUFFER_UNKNOWN;
138 	m_isSensitive = false;
139 
140 }
141 
safeBuffer(const char * inStr,XMLSize_t initialSize)142 safeBuffer::safeBuffer(const char * inStr, XMLSize_t initialSize) {
143     // Initialise with a string
144     bufferSize = ((XMLSize_t) strlen(inStr) > initialSize ? (XMLSize_t) (strlen(inStr) * 2) : initialSize);
145 
146 	buffer = new unsigned char[bufferSize];
147 	memset((void *) buffer, 0, bufferSize);
148 	strcpy((char *) buffer, inStr);
149 	mp_XMLCh = NULL;
150 	m_bufferType = BUFFER_CHAR;
151 	m_isSensitive = false;
152 
153 }
154 
safeBuffer(const safeBuffer & other)155 safeBuffer::safeBuffer(const safeBuffer & other) {
156 
157 	// Copy constructor
158 
159 	bufferSize = other.bufferSize;
160 	buffer = new unsigned char [bufferSize];
161 
162 	memcpy(buffer, other.buffer, bufferSize);
163 
164 	if (other.mp_XMLCh != NULL) {
165 
166 		mp_XMLCh = XMLString::replicate(other.mp_XMLCh);
167 
168 	}
169 	else {
170 
171 		mp_XMLCh = NULL;
172 
173 	}
174 
175 	m_bufferType = other.m_bufferType;
176 	m_isSensitive = other.m_isSensitive;
177 
178 }
179 
~safeBuffer()180 safeBuffer::~safeBuffer() {
181 
182 
183 	if (buffer != NULL) {
184 		if (m_isSensitive == true)
185 			cleanseBuffer();
186 		delete[] buffer;
187 	}
188 
189 	if (mp_XMLCh != NULL)
190 		XSEC_RELEASE_XMLCH(mp_XMLCh);
191 
192 }
193 
init(void)194 void safeBuffer::init (void) {
195 
196 	size_XMLCh = sizeof(XMLCh);
197 
198 }
199 
200 // "IN" functions - these read in information to the buffer
201 
sbStrcpyIn(const char * inStr)202 void safeBuffer::sbStrcpyIn(const char * inStr) {
203 
204 	// Copy a string into the safe buffer
205     checkAndExpand((XMLSize_t) strlen(inStr));
206 	strcpy((char *) buffer, inStr);
207 	m_bufferType = BUFFER_CHAR;
208 
209 }
210 
sbStrcpyIn(const safeBuffer & inStr)211 void safeBuffer::sbStrcpyIn(const safeBuffer & inStr) {
212 
213 	inStr.checkBufferType(BUFFER_CHAR);
214     checkAndExpand((XMLSize_t) strlen((char *) inStr.buffer));
215 	strcpy((char *) buffer, (char *) inStr.buffer);
216 	m_bufferType = BUFFER_CHAR;
217 
218 }
219 
220 
sbStrncpyIn(const char * inStr,XMLSize_t n)221 void safeBuffer::sbStrncpyIn(const char * inStr, XMLSize_t n) {
222     XMLSize_t len = (XMLSize_t) strlen(inStr);
223 	checkAndExpand((n < len) ? n : len);
224 	strncpy((char *) buffer, inStr, n);
225 	buffer[n] = '\0';
226 	m_bufferType = BUFFER_CHAR;
227 
228 }
229 
sbStrncpyIn(const safeBuffer & inStr,XMLSize_t n)230 void safeBuffer::sbStrncpyIn(const safeBuffer & inStr, XMLSize_t n) {
231 
232 	inStr.checkBufferType(BUFFER_CHAR);
233 	checkAndExpand(n);
234 	strncpy((char *) buffer, (char *) inStr.buffer, n);
235 	buffer[n] = '\0';
236 	m_bufferType = BUFFER_CHAR;
237 
238 
239 }
240 
241 
sbStrcatIn(const char * inStr)242 void safeBuffer::sbStrcatIn(const char * inStr) {
243 
244 	checkBufferType(BUFFER_CHAR);
245     checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen(inStr) + 1));
246 	strcat((char *) buffer, inStr);
247 
248 }
249 
sbStrcatIn(const safeBuffer & inStr)250 void safeBuffer::sbStrcatIn(const safeBuffer & inStr) {
251 
252 	checkBufferType(BUFFER_CHAR);
253     checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen((char *) inStr.buffer) + 2));
254 	strcat((char *) buffer, (char *) inStr.buffer);
255 
256 }
257 
sbStrncatIn(const char * inStr,XMLSize_t n)258 void safeBuffer::sbStrncatIn(const char * inStr, XMLSize_t n) {
259     checkBufferType(BUFFER_CHAR);
260     XMLSize_t len = (XMLSize_t) strlen(inStr);
261 	XMLSize_t totalLen = ((n < len) ? n : len) + (XMLSize_t)strlen((char *)buffer);
262     checkAndExpand(totalLen + 2);
263 	strncat((char *) buffer, inStr, n);
264 	buffer[totalLen] = '\0';
265 
266 }
267 
sbMemcpyIn(const void * inBuf,XMLSize_t n)268 void safeBuffer::sbMemcpyIn(const void * inBuf, XMLSize_t n) {
269 
270 	checkAndExpand(n);
271 	memcpy(buffer, inBuf, n);
272 	m_bufferType = BUFFER_UNKNOWN;
273 
274 }
275 
sbMemcpyIn(XMLSize_t offset,const void * inBuf,XMLSize_t n)276 void safeBuffer::sbMemcpyIn(XMLSize_t offset, const void * inBuf, XMLSize_t n) {
277 
278 	checkAndExpand(n + offset);
279 	memcpy(&buffer[offset], inBuf, n);
280 	m_bufferType = BUFFER_UNKNOWN;
281 }
282 
sbStrinsIn(const char * inStr,XMLSize_t offset)283 void safeBuffer::sbStrinsIn(const char * inStr, XMLSize_t offset) {
284 
285     checkBufferType(BUFFER_CHAR);
286 
287     XMLSize_t bl = (XMLSize_t) strlen((char *) buffer);
288     XMLSize_t il = (XMLSize_t) strlen((char *) inStr);
289 
290 	if (offset > bl) {
291 		throw XSECException(XSECException::SafeBufferError,
292 			"Attempt to insert string after termination point");
293 	}
294 
295 	checkAndExpand(bl + il + 1);
296 
297 	memmove(&buffer[offset + il], &buffer[offset], bl - offset + 1);
298 	memcpy(&buffer[offset], inStr, il);
299 
300 }
301 
sbMemcpyOut(void * outBuf,XMLSize_t n) const302 void safeBuffer::sbMemcpyOut(void *outBuf, XMLSize_t n) const {
303 
304 	// WARNING - JUST ASSUMES OUTPUT BUFFER LONG ENOUGH
305 	// ALSO MAKES NO ASSUMPTION OF THE BUFFER TYPE
306 
307 	if (n > bufferSize) {
308 		throw XSECException(XSECException::SafeBufferError,
309 			"safeBuffer::sbMemcpyOut Attempt to copy more data than buffer can hold");
310 	}
311 
312 	memcpy(outBuf, buffer, n);
313 
314 }
315 
sbMemshift(XMLSize_t toOffset,XMLSize_t fromOffset,XMLSize_t len)316 void safeBuffer::sbMemshift(XMLSize_t toOffset, XMLSize_t fromOffset, XMLSize_t len) {
317 
318 	// Move data in the buffer around
319 	checkAndExpand(len + (toOffset > fromOffset ? toOffset : fromOffset));
320 
321 	memmove(&buffer[toOffset], &buffer[fromOffset], len);
322 
323 }
324 
325 
326 // Comparisons
327 
sbStrncmp(const char * inStr,XMLSize_t n) const328 int safeBuffer::sbStrncmp(const char *inStr, XMLSize_t n) const {
329 
330 	checkBufferType(BUFFER_CHAR);
331 	return (strncmp((char *) buffer, inStr, n));
332 
333 }
334 
sbStrcmp(const char * inStr) const335 int safeBuffer::sbStrcmp(const char *inStr) const {
336 
337 	checkBufferType(BUFFER_CHAR);
338 	return (strcmp((char *) buffer, inStr));
339 
340 }
341 
sbStrcmp(const safeBuffer & inStr) const342 int safeBuffer::sbStrcmp(const safeBuffer & inStr) const {
343 
344 	checkBufferType(BUFFER_CHAR);
345 	return (strcmp((char *) buffer, (char *) inStr.buffer));
346 
347 }
348 
sbOffsetStrcmp(const char * inStr,XMLSize_t offset) const349 int safeBuffer::sbOffsetStrcmp(const char * inStr, XMLSize_t offset) const {
350 
351     checkBufferType(BUFFER_CHAR);
352     XMLSize_t bl = (XMLSize_t) strlen((char *) buffer);
353 
354 	if (offset > bl)
355 		return -1;
356 
357 	return (strcmp((char *) &buffer[offset], inStr));
358 
359 }
360 
sbStrstr(const char * inStr) const361 XMLSSize_t safeBuffer::sbStrstr(const char * inStr) const {
362 
363 	checkBufferType(BUFFER_CHAR);
364 	const char* p = strstr((char *) buffer, inStr);
365 
366 	if (p == NULL)
367 		return -1;
368 
369 	XMLSSize_t d = p - (char*) buffer;
370 	if (d > bufferSize || d < 0)
371 		return -1;
372 
373 	return d;
374 
375 }
376 
sbOffsetStrstr(const char * inStr,XMLSize_t offset) const377 XMLSSize_t safeBuffer::sbOffsetStrstr(const char * inStr, XMLSize_t offset) const {
378 
379 	checkBufferType(BUFFER_CHAR);
380 	XMLSize_t bl = strlen((char *) buffer);
381 
382 	if (offset > bl)
383 		return -1;
384 
385 	const char* p = strstr((char *) &buffer[offset], inStr);
386 
387 	if (p == NULL)
388 		return -1;
389 
390 	XMLSSize_t d = p - (char*) buffer;
391 	if (d > bufferSize || d < 0)
392 		return -1;
393 
394 	return d;
395 
396 }
397 
398 // XMLCh and char common functions
399 
sbStrlwr(void)400 void safeBuffer::sbStrlwr(void) {
401 
402 	if (m_bufferType == BUFFER_UNKNOWN) {
403 
404 		throw XSECException(XSECException::SafeBufferError,
405 			"Attempt to perform an operation on a buffer of incorrect type");
406 
407 	}
408 
409 	if (m_bufferType == BUFFER_CHAR) {
410 
411 	    XMLSize_t i, l = (XMLSize_t) strlen((char *) buffer);
412 
413 		for (i = 0; i < l; ++i) {
414 			if (buffer[i] >= 'A' && buffer[i] <= 'Z')
415 				buffer[i] = (buffer[i] - 'A') + 'a';
416 		}
417 
418 	}
419 
420 	else {
421 
422 		XMLCh * b = (XMLCh *) buffer;
423 		XMLSize_t i, l = XMLString::stringLen(b);
424 
425 		for (i = 0; i < l; ++i) {
426 			if (b[i] >= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A && b[i] <= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_Z)
427 				b[i] = (b[i] - XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A) + XERCES_CPP_NAMESPACE_QUALIFIER chLatin_a;
428 		}
429 
430 	}
431 
432 }
433 // Operators
434 
operator [](XMLSize_t n)435 unsigned char & safeBuffer::operator[](XMLSize_t n) {
436 
437 	// If the character is outside our range (but +ve), then simply increase
438 	// the buffer size - NOTE: it is not our problem if the caller does
439 	// not realise they are outside the buffer, we are simply trying to ensure
440 	// the call is "safe"
441 
442 	checkAndExpand(n);
443 
444 	return buffer[n];
445 
446 }
447 
operator =(const safeBuffer & cpy)448 safeBuffer & safeBuffer::operator= (const safeBuffer & cpy) {
449 
450 	if (bufferSize != cpy.bufferSize) {
451 
452 		if (bufferSize != 0) {
453 
454 			if (m_isSensitive == true)
455 				cleanseBuffer();
456 
457 			delete [] buffer;
458 		}
459 
460 		buffer = new unsigned char [cpy.bufferSize];
461 		bufferSize = cpy.bufferSize;
462 
463 	}
464 
465 	memcpy(buffer, cpy.buffer, bufferSize);
466 	m_bufferType = cpy.m_bufferType;
467 	// Once we are sensitive, we are always sensitive
468 	m_isSensitive = m_isSensitive || cpy.m_isSensitive;
469 
470 	return *this;
471 }
472 
operator =(const XMLCh * inStr)473 safeBuffer & safeBuffer::operator= (const XMLCh * inStr) {
474 
475 	checkAndExpand(XMLString::stringLen(inStr) * size_XMLCh);
476 	XMLString::copyString((XMLCh *) buffer, inStr);
477 	m_bufferType = BUFFER_UNICODE;
478 	return *this;
479 
480 }
481 
operator <<(TXFMBase * t)482 safeBuffer & safeBuffer::operator << (TXFMBase * t) {
483 
484 	// Read into buffer the output of the transform
485 	XMLSize_t offset = 0;
486 	unsigned char inBuf[2048];
487 	XMLSize_t bytesRead;
488 
489 	while ((bytesRead = t->readBytes(inBuf, 2000)) > 0) {
490 
491 		checkAndExpand(offset + bytesRead + 1);
492 		memcpy(&buffer[offset], inBuf, bytesRead);
493 		offset += bytesRead;
494 
495 	}
496 
497 	m_bufferType = BUFFER_CHAR;
498 	buffer[offset] = '\0';
499 
500 	return *this;
501 }
502 
503 
504 // Unicode Functions
505 
sbStrToXMLCh(void) const506 const XMLCh * safeBuffer::sbStrToXMLCh(void) const {
507 
508 	checkBufferType(BUFFER_CHAR);
509 	if (mp_XMLCh != NULL)
510 		XSEC_RELEASE_XMLCH(mp_XMLCh);
511 
512 	mp_XMLCh = XMLString::transcode((char *) buffer);
513 
514 	return mp_XMLCh;
515 
516 }
517 
sbTranscodeIn(const XMLCh * inStr)518 void safeBuffer::sbTranscodeIn(const XMLCh * inStr) {
519 
520 	// Transcode the string to the local code page and store in the buffer
521 	char * t;
522 
523 	t = XMLString::transcode(inStr);
524 
525 	assert (t != 0);
526 
527 
528 	// Now copy into our local buffer - a bit inefficient but better in the long run
529 	// as a buffer that is the exact size is likely to be deleted anyway during a
530 	// concat operation
531 
532 	XMLSize_t len = (XMLSize_t) strlen(t) + 1;
533 	checkAndExpand(len);
534 	strcpy((char *) buffer, t);
535 	m_bufferType = BUFFER_CHAR;
536 
537 	XSEC_RELEASE_XMLCH(t);
538 
539 }
540 
sbTranscodeIn(const char * inStr)541 void safeBuffer::sbTranscodeIn(const char * inStr) {
542 
543 	// Transcode the string to the local code page and store in the buffer
544 	XMLCh * t;
545 
546 	t = XMLString::transcode(inStr);
547 
548 	assert (t != 0);
549 
550 	// Copy into local buffer
551 
552 	XMLSize_t len = XMLString::stringLen(t) + 1;
553     len *= (XMLSize_t) size_XMLCh;
554 	checkAndExpand(len);
555 
556 	XMLString::copyString((XMLCh *) buffer, t);
557 	m_bufferType = BUFFER_UNICODE;
558 
559 	XSEC_RELEASE_XMLCH(t);
560 
561 }
562 
563 
sbXMLChIn(const XMLCh * in)564 void safeBuffer::sbXMLChIn(const XMLCh * in) {
565 
566 	checkAndExpand((XMLString::stringLen(in) + 1) * size_XMLCh);
567 
568 	XMLString::copyString((XMLCh *) buffer, in);
569 	m_bufferType = BUFFER_UNICODE;
570 
571 }
572 
sbXMLChAppendCh(const XMLCh c)573 void safeBuffer::sbXMLChAppendCh(const XMLCh c) {
574 
575 	checkBufferType(BUFFER_UNICODE);
576 	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer);
577 
578 	checkAndExpand((len + 2) * size_XMLCh);
579 
580 	((XMLCh *) buffer)[len++] = c;
581 	((XMLCh *) buffer)[len] = 0;
582 
583 }
584 
sbXMLChCat(const XMLCh * str)585 void safeBuffer::sbXMLChCat(const XMLCh *str) {
586 
587 	checkBufferType(BUFFER_UNICODE);
588 	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh;
589 	len += XMLString::stringLen(str) * size_XMLCh;
590 	len += (2 * ((XMLSize_t) size_XMLCh));
591 
592 	checkAndExpand(len);
593 
594 	XMLString::catString((XMLCh *) buffer, str);
595 
596 }
597 
sbXMLChCat(const char * str)598 void safeBuffer::sbXMLChCat(const char * str) {
599 
600 	checkBufferType(BUFFER_UNICODE);
601 	XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh;
602 
603 	XMLCh * t = XMLString::transcode(str);
604 
605 	assert (t != NULL);
606 
607 	len += XMLString::stringLen(t) * size_XMLCh;
608 	len += (XMLSize_t) (2 * size_XMLCh);
609 
610 	checkAndExpand(len);
611 
612 	XMLString::catString((XMLCh *) buffer, t);
613 
614 	XSEC_RELEASE_XMLCH(t);
615 }
616 
sbXMLChCat8(const char * str)617 void safeBuffer::sbXMLChCat8(const char * str) {
618 
619 	checkBufferType(BUFFER_UNICODE);
620 
621 	XMLCh * toAdd = transcodeFromUTF8((const unsigned char *) str);
622 	sbXMLChCat(toAdd);
623 	XSEC_RELEASE_XMLCH(toAdd);
624 
625 }
626 
627 // Get functions
628 
sbStrlen(void) const629 XMLSize_t safeBuffer::sbStrlen(void) const {
630 
631     checkBufferType(BUFFER_CHAR);
632     return (XMLSize_t) (strlen ((char *) buffer));
633 
634 }
635 
sbRawBufferSize(void) const636 XMLSize_t safeBuffer::sbRawBufferSize(void) const {
637 
638     return bufferSize;
639 
640 }
641 
642 
643 // raw buffer manipulation
644 
rawBuffer() const645 const unsigned char * safeBuffer::rawBuffer() const {
646 
647 	return buffer;
648 
649 }
650 
rawCharBuffer() const651 const char * safeBuffer::rawCharBuffer() const {
652 
653 	return (char *) buffer;
654 
655 }
656 
rawXMLChBuffer() const657 const XMLCh * safeBuffer::rawXMLChBuffer() const {
658 
659 	return (XMLCh *) buffer;
660 
661 }
662 
663 // Sensitive data functions
664 
isSensitive(void)665 void safeBuffer::isSensitive(void) {
666 
667 	m_isSensitive = true;
668 
669 }
670 
cleanseBuffer(void)671 void safeBuffer::cleanseBuffer(void) {
672 
673 	// Cleanse the main buffer
674 	for (XMLSize_t i = 0; i < bufferSize; ++i)
675 		buffer[i] = 0;
676 
677 }
678