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