| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * XSECSafeBuffer := a class for storing expanding amounts of information. |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| // XSEC includes |
| |
| #include <xsec/utils/XSECSafeBuffer.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/transformers/TXFMBase.hpp> |
| |
| #include "XSECDOMUtils.hpp" |
| |
| #include <xercesc/util/XMLUniDefs.hpp> |
| |
| XSEC_USING_XERCES(XMLString); |
| |
| // Standard includes |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| size_t safeBuffer::size_XMLCh; |
| |
| #if defined (_MSC_VER) |
| #pragma warning(disable: 4311) |
| #endif |
| |
| void safeBuffer::checkAndExpand(XMLSize_t size) { |
| |
| // For a given size, check it will fit (with one byte spare) |
| // and expand if necessary |
| |
| if (bufferSize >= 2 && size < bufferSize - 2) { |
| return; |
| } |
| |
| if (size > XERCES_SIZE_MAX - DEFAULT_SAFE_BUFFER_SIZE) { |
| /* We've got a string that's too big to deal with */ |
| throw XSECException(XSECException::SafeBufferError, |
| "Buffer has grown too large"); |
| } |
| |
| // Resize and add 1K for further growth |
| XMLSize_t newBufferSize = size + DEFAULT_SAFE_BUFFER_SIZE; |
| |
| unsigned char * newBuffer = new unsigned char[newBufferSize]; |
| if (newBuffer == NULL) |
| { |
| /* Ran out of memory */ |
| throw XSECException(XSECException::MemoryAllocationFail, |
| "Error allocating memory for Buffer"); |
| } |
| |
| memset((void *) newBuffer, 0, newBufferSize); |
| memcpy(newBuffer, buffer, bufferSize); |
| |
| // If we are sensitive, clean the old buffer |
| if (m_isSensitive == true) |
| cleanseBuffer(); |
| |
| // clean up |
| bufferSize = newBufferSize; |
| delete[] buffer; |
| buffer = newBuffer; |
| } |
| |
| void safeBuffer::checkBufferType(bufferType bt) const { |
| |
| if (bt != m_bufferType) { |
| |
| throw XSECException(XSECException::SafeBufferError, |
| "Attempt to perform an operation on a buffer of incorrect type"); |
| } |
| |
| } |
| |
| |
| void safeBuffer::setBufferType(bufferType bt) { |
| |
| m_bufferType = bt; |
| |
| } |
| |
| void safeBuffer::resize(XMLSize_t sz) { |
| |
| checkAndExpand(sz); |
| |
| } |
| |
| safeBuffer::safeBuffer(XMLSize_t initialSize) { |
| |
| // Initialise the buffer with a set size string |
| |
| bufferSize = initialSize; |
| buffer = new unsigned char[initialSize]; |
| memset((void *) buffer, 0, bufferSize); |
| mp_XMLCh = NULL; |
| m_bufferType = BUFFER_UNKNOWN; |
| m_isSensitive = false; |
| |
| } |
| |
| safeBuffer::safeBuffer() { |
| |
| bufferSize = DEFAULT_SAFE_BUFFER_SIZE; |
| buffer = new unsigned char[bufferSize]; |
| memset((void *) buffer, 0, bufferSize); |
| mp_XMLCh = NULL; |
| m_bufferType = BUFFER_UNKNOWN; |
| m_isSensitive = false; |
| |
| } |
| |
| safeBuffer::safeBuffer(const char * inStr, XMLSize_t initialSize) { |
| // Initialise with a string |
| bufferSize = ((XMLSize_t) strlen(inStr) > initialSize ? (XMLSize_t) (strlen(inStr) * 2) : initialSize); |
| |
| buffer = new unsigned char[bufferSize]; |
| memset((void *) buffer, 0, bufferSize); |
| strcpy((char *) buffer, inStr); |
| mp_XMLCh = NULL; |
| m_bufferType = BUFFER_CHAR; |
| m_isSensitive = false; |
| |
| } |
| |
| safeBuffer::safeBuffer(const safeBuffer & other) { |
| |
| // Copy constructor |
| |
| bufferSize = other.bufferSize; |
| buffer = new unsigned char [bufferSize]; |
| |
| memcpy(buffer, other.buffer, bufferSize); |
| |
| if (other.mp_XMLCh != NULL) { |
| |
| mp_XMLCh = XMLString::replicate(other.mp_XMLCh); |
| |
| } |
| else { |
| |
| mp_XMLCh = NULL; |
| |
| } |
| |
| m_bufferType = other.m_bufferType; |
| m_isSensitive = other.m_isSensitive; |
| |
| } |
| |
| safeBuffer::~safeBuffer() { |
| |
| |
| if (buffer != NULL) { |
| if (m_isSensitive == true) |
| cleanseBuffer(); |
| delete[] buffer; |
| } |
| |
| if (mp_XMLCh != NULL) |
| XSEC_RELEASE_XMLCH(mp_XMLCh); |
| |
| } |
| |
| void safeBuffer::init (void) { |
| |
| size_XMLCh = sizeof(XMLCh); |
| |
| } |
| |
| // "IN" functions - these read in information to the buffer |
| |
| void safeBuffer::sbStrcpyIn(const char * inStr) { |
| |
| // Copy a string into the safe buffer |
| checkAndExpand((XMLSize_t) strlen(inStr)); |
| strcpy((char *) buffer, inStr); |
| m_bufferType = BUFFER_CHAR; |
| |
| } |
| |
| void safeBuffer::sbStrcpyIn(const safeBuffer & inStr) { |
| |
| inStr.checkBufferType(BUFFER_CHAR); |
| checkAndExpand((XMLSize_t) strlen((char *) inStr.buffer)); |
| strcpy((char *) buffer, (char *) inStr.buffer); |
| m_bufferType = BUFFER_CHAR; |
| |
| } |
| |
| |
| void safeBuffer::sbStrncpyIn(const char * inStr, XMLSize_t n) { |
| XMLSize_t len = (XMLSize_t) strlen(inStr); |
| checkAndExpand((n < len) ? n : len); |
| strncpy((char *) buffer, inStr, n); |
| buffer[n] = '\0'; |
| m_bufferType = BUFFER_CHAR; |
| |
| } |
| |
| void safeBuffer::sbStrncpyIn(const safeBuffer & inStr, XMLSize_t n) { |
| |
| inStr.checkBufferType(BUFFER_CHAR); |
| checkAndExpand(n); |
| strncpy((char *) buffer, (char *) inStr.buffer, n); |
| buffer[n] = '\0'; |
| m_bufferType = BUFFER_CHAR; |
| |
| |
| } |
| |
| |
| void safeBuffer::sbStrcatIn(const char * inStr) { |
| |
| checkBufferType(BUFFER_CHAR); |
| checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen(inStr) + 1)); |
| strcat((char *) buffer, inStr); |
| |
| } |
| |
| void safeBuffer::sbStrcatIn(const safeBuffer & inStr) { |
| |
| checkBufferType(BUFFER_CHAR); |
| checkAndExpand((XMLSize_t) (strlen((char *) buffer) + strlen((char *) inStr.buffer) + 2)); |
| strcat((char *) buffer, (char *) inStr.buffer); |
| |
| } |
| |
| void safeBuffer::sbStrncatIn(const char * inStr, XMLSize_t n) { |
| checkBufferType(BUFFER_CHAR); |
| XMLSize_t len = (XMLSize_t) strlen(inStr); |
| XMLSize_t totalLen = ((n < len) ? n : len) + (XMLSize_t)strlen((char *)buffer); |
| checkAndExpand(totalLen + 2); |
| strncat((char *) buffer, inStr, n); |
| buffer[totalLen] = '\0'; |
| |
| } |
| |
| void safeBuffer::sbMemcpyIn(const void * inBuf, XMLSize_t n) { |
| |
| checkAndExpand(n); |
| memcpy(buffer, inBuf, n); |
| m_bufferType = BUFFER_UNKNOWN; |
| |
| } |
| |
| void safeBuffer::sbMemcpyIn(XMLSize_t offset, const void * inBuf, XMLSize_t n) { |
| |
| checkAndExpand(n + offset); |
| memcpy(&buffer[offset], inBuf, n); |
| m_bufferType = BUFFER_UNKNOWN; |
| } |
| |
| void safeBuffer::sbStrinsIn(const char * inStr, XMLSize_t offset) { |
| |
| checkBufferType(BUFFER_CHAR); |
| |
| XMLSize_t bl = (XMLSize_t) strlen((char *) buffer); |
| XMLSize_t il = (XMLSize_t) strlen((char *) inStr); |
| |
| if (offset > bl) { |
| throw XSECException(XSECException::SafeBufferError, |
| "Attempt to insert string after termination point"); |
| } |
| |
| checkAndExpand(bl + il + 1); |
| |
| memmove(&buffer[offset + il], &buffer[offset], bl - offset + 1); |
| memcpy(&buffer[offset], inStr, il); |
| |
| } |
| |
| void safeBuffer::sbMemcpyOut(void *outBuf, XMLSize_t n) const { |
| |
| // WARNING - JUST ASSUMES OUTPUT BUFFER LONG ENOUGH |
| // ALSO MAKES NO ASSUMPTION OF THE BUFFER TYPE |
| |
| if (n > bufferSize) { |
| throw XSECException(XSECException::SafeBufferError, |
| "safeBuffer::sbMemcpyOut Attempt to copy more data than buffer can hold"); |
| } |
| |
| memcpy(outBuf, buffer, n); |
| |
| } |
| |
| void safeBuffer::sbMemshift(XMLSize_t toOffset, XMLSize_t fromOffset, XMLSize_t len) { |
| |
| // Move data in the buffer around |
| checkAndExpand(len + (toOffset > fromOffset ? toOffset : fromOffset)); |
| |
| memmove(&buffer[toOffset], &buffer[fromOffset], len); |
| |
| } |
| |
| |
| // Comparisons |
| |
| int safeBuffer::sbStrncmp(const char *inStr, XMLSize_t n) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| return (strncmp((char *) buffer, inStr, n)); |
| |
| } |
| |
| int safeBuffer::sbStrcmp(const char *inStr) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| return (strcmp((char *) buffer, inStr)); |
| |
| } |
| |
| int safeBuffer::sbStrcmp(const safeBuffer & inStr) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| return (strcmp((char *) buffer, (char *) inStr.buffer)); |
| |
| } |
| |
| int safeBuffer::sbOffsetStrcmp(const char * inStr, XMLSize_t offset) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| XMLSize_t bl = (XMLSize_t) strlen((char *) buffer); |
| |
| if (offset > bl) |
| return -1; |
| |
| return (strcmp((char *) &buffer[offset], inStr)); |
| |
| } |
| |
| XMLSSize_t safeBuffer::sbStrstr(const char * inStr) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| const char* p = strstr((char *) buffer, inStr); |
| |
| if (p == NULL) |
| return -1; |
| |
| XMLSSize_t d = p - (char*) buffer; |
| if (d > bufferSize || d < 0) |
| return -1; |
| |
| return d; |
| |
| } |
| |
| XMLSSize_t safeBuffer::sbOffsetStrstr(const char * inStr, XMLSize_t offset) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| XMLSize_t bl = strlen((char *) buffer); |
| |
| if (offset > bl) |
| return -1; |
| |
| const char* p = strstr((char *) &buffer[offset], inStr); |
| |
| if (p == NULL) |
| return -1; |
| |
| XMLSSize_t d = p - (char*) buffer; |
| if (d > bufferSize || d < 0) |
| return -1; |
| |
| return d; |
| |
| } |
| |
| // XMLCh and char common functions |
| |
| void safeBuffer::sbStrlwr(void) { |
| |
| if (m_bufferType == BUFFER_UNKNOWN) { |
| |
| throw XSECException(XSECException::SafeBufferError, |
| "Attempt to perform an operation on a buffer of incorrect type"); |
| |
| } |
| |
| if (m_bufferType == BUFFER_CHAR) { |
| |
| XMLSize_t i, l = (XMLSize_t) strlen((char *) buffer); |
| |
| for (i = 0; i < l; ++i) { |
| if (buffer[i] >= 'A' && buffer[i] <= 'Z') |
| buffer[i] = (buffer[i] - 'A') + 'a'; |
| } |
| |
| } |
| |
| else { |
| |
| XMLCh * b = (XMLCh *) buffer; |
| XMLSize_t i, l = XMLString::stringLen(b); |
| |
| for (i = 0; i < l; ++i) { |
| if (b[i] >= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A && b[i] <= XERCES_CPP_NAMESPACE_QUALIFIER chLatin_Z) |
| b[i] = (b[i] - XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A) + XERCES_CPP_NAMESPACE_QUALIFIER chLatin_a; |
| } |
| |
| } |
| |
| } |
| // Operators |
| |
| unsigned char & safeBuffer::operator[](XMLSize_t n) { |
| |
| // If the character is outside our range (but +ve), then simply increase |
| // the buffer size - NOTE: it is not our problem if the caller does |
| // not realise they are outside the buffer, we are simply trying to ensure |
| // the call is "safe" |
| |
| checkAndExpand(n); |
| |
| return buffer[n]; |
| |
| } |
| |
| safeBuffer & safeBuffer::operator= (const safeBuffer & cpy) { |
| |
| if (bufferSize != cpy.bufferSize) { |
| |
| if (bufferSize != 0) { |
| |
| if (m_isSensitive == true) |
| cleanseBuffer(); |
| |
| delete [] buffer; |
| } |
| |
| buffer = new unsigned char [cpy.bufferSize]; |
| bufferSize = cpy.bufferSize; |
| |
| } |
| |
| memcpy(buffer, cpy.buffer, bufferSize); |
| m_bufferType = cpy.m_bufferType; |
| // Once we are sensitive, we are always sensitive |
| m_isSensitive = m_isSensitive || cpy.m_isSensitive; |
| |
| return *this; |
| } |
| |
| safeBuffer & safeBuffer::operator= (const XMLCh * inStr) { |
| |
| checkAndExpand(XMLString::stringLen(inStr) * size_XMLCh); |
| XMLString::copyString((XMLCh *) buffer, inStr); |
| m_bufferType = BUFFER_UNICODE; |
| return *this; |
| |
| } |
| |
| safeBuffer & safeBuffer::operator << (TXFMBase * t) { |
| |
| // Read into buffer the output of the transform |
| XMLSize_t offset = 0; |
| unsigned char inBuf[2048]; |
| XMLSize_t bytesRead; |
| |
| while ((bytesRead = t->readBytes(inBuf, 2000)) > 0) { |
| |
| checkAndExpand(offset + bytesRead + 1); |
| memcpy(&buffer[offset], inBuf, bytesRead); |
| offset += bytesRead; |
| |
| } |
| |
| m_bufferType = BUFFER_CHAR; |
| buffer[offset] = '\0'; |
| |
| return *this; |
| } |
| |
| |
| // Unicode Functions |
| |
| const XMLCh * safeBuffer::sbStrToXMLCh(void) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| if (mp_XMLCh != NULL) |
| XSEC_RELEASE_XMLCH(mp_XMLCh); |
| |
| mp_XMLCh = XMLString::transcode((char *) buffer); |
| |
| return mp_XMLCh; |
| |
| } |
| |
| void safeBuffer::sbTranscodeIn(const XMLCh * inStr) { |
| |
| // Transcode the string to the local code page and store in the buffer |
| char * t; |
| |
| t = XMLString::transcode(inStr); |
| |
| assert (t != 0); |
| |
| |
| // Now copy into our local buffer - a bit inefficient but better in the long run |
| // as a buffer that is the exact size is likely to be deleted anyway during a |
| // concat operation |
| |
| XMLSize_t len = (XMLSize_t) strlen(t) + 1; |
| checkAndExpand(len); |
| strcpy((char *) buffer, t); |
| m_bufferType = BUFFER_CHAR; |
| |
| XSEC_RELEASE_XMLCH(t); |
| |
| } |
| |
| void safeBuffer::sbTranscodeIn(const char * inStr) { |
| |
| // Transcode the string to the local code page and store in the buffer |
| XMLCh * t; |
| |
| t = XMLString::transcode(inStr); |
| |
| assert (t != 0); |
| |
| // Copy into local buffer |
| |
| XMLSize_t len = XMLString::stringLen(t) + 1; |
| len *= (XMLSize_t) size_XMLCh; |
| checkAndExpand(len); |
| |
| XMLString::copyString((XMLCh *) buffer, t); |
| m_bufferType = BUFFER_UNICODE; |
| |
| XSEC_RELEASE_XMLCH(t); |
| |
| } |
| |
| |
| void safeBuffer::sbXMLChIn(const XMLCh * in) { |
| |
| checkAndExpand((XMLString::stringLen(in) + 1) * size_XMLCh); |
| |
| XMLString::copyString((XMLCh *) buffer, in); |
| m_bufferType = BUFFER_UNICODE; |
| |
| } |
| |
| void safeBuffer::sbXMLChAppendCh(const XMLCh c) { |
| |
| checkBufferType(BUFFER_UNICODE); |
| XMLSize_t len = XMLString::stringLen((XMLCh *) buffer); |
| |
| checkAndExpand((len + 2) * size_XMLCh); |
| |
| ((XMLCh *) buffer)[len++] = c; |
| ((XMLCh *) buffer)[len] = 0; |
| |
| } |
| |
| void safeBuffer::sbXMLChCat(const XMLCh *str) { |
| |
| checkBufferType(BUFFER_UNICODE); |
| XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh; |
| len += XMLString::stringLen(str) * size_XMLCh; |
| len += (2 * ((XMLSize_t) size_XMLCh)); |
| |
| checkAndExpand(len); |
| |
| XMLString::catString((XMLCh *) buffer, str); |
| |
| } |
| |
| void safeBuffer::sbXMLChCat(const char * str) { |
| |
| checkBufferType(BUFFER_UNICODE); |
| XMLSize_t len = XMLString::stringLen((XMLCh *) buffer) * size_XMLCh; |
| |
| XMLCh * t = XMLString::transcode(str); |
| |
| assert (t != NULL); |
| |
| len += XMLString::stringLen(t) * size_XMLCh; |
| len += (XMLSize_t) (2 * size_XMLCh); |
| |
| checkAndExpand(len); |
| |
| XMLString::catString((XMLCh *) buffer, t); |
| |
| XSEC_RELEASE_XMLCH(t); |
| } |
| |
| void safeBuffer::sbXMLChCat8(const char * str) { |
| |
| checkBufferType(BUFFER_UNICODE); |
| |
| XMLCh * toAdd = transcodeFromUTF8((const unsigned char *) str); |
| sbXMLChCat(toAdd); |
| XSEC_RELEASE_XMLCH(toAdd); |
| |
| } |
| |
| // Get functions |
| |
| XMLSize_t safeBuffer::sbStrlen(void) const { |
| |
| checkBufferType(BUFFER_CHAR); |
| return (XMLSize_t) (strlen ((char *) buffer)); |
| |
| } |
| |
| XMLSize_t safeBuffer::sbRawBufferSize(void) const { |
| |
| return bufferSize; |
| |
| } |
| |
| |
| // raw buffer manipulation |
| |
| const unsigned char * safeBuffer::rawBuffer() const { |
| |
| return buffer; |
| |
| } |
| |
| const char * safeBuffer::rawCharBuffer() const { |
| |
| return (char *) buffer; |
| |
| } |
| |
| const XMLCh * safeBuffer::rawXMLChBuffer() const { |
| |
| return (XMLCh *) buffer; |
| |
| } |
| |
| // Sensitive data functions |
| |
| void safeBuffer::isSensitive(void) { |
| |
| m_isSensitive = true; |
| |
| } |
| |
| void safeBuffer::cleanseBuffer(void) { |
| |
| // Cleanse the main buffer |
| for (XMLSize_t i = 0; i < bufferSize; ++i) |
| buffer[i] = 0; |
| |
| } |