*** /dev/null Sat Nov 23 01:18:21 2024
--- - Sat Nov 23 01:18:33 2024
***************
*** 0 ****
--- 1,226 ----
+ /*
+ XDS - OSSP Extensible Data Serialization Library
+ Copyright (c) 2001 The OSSP Project (http://www.ossp.org/)
+ Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/)
+
+ This file is part of OSSP XDS, an extensible data serialization
+ library which can be found at http://www.ossp.com/pkg/xds/.
+
+ Permission to use, copy, modify, and distribute this software for
+ any purpose with or without fee is hereby granted, provided that
+ the above copyright notice and this permission notice appear in all
+ copies.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ */
+
+ #include <string.h>
+ #include <ctype.h>
+ #include "xds.h"
+
+ static int base64_decode(unsigned char *dst, size_t dstlen, char const *src, size_t srclen)
+ {
+ int dstidx, state, ch = 0;
+ unsigned char res;
+ char *pos;
+
+ if (srclen == 0)
+ srclen = strlen(src);
+ state = 0;
+ dstidx = 0;
+ res = 0;
+ while (srclen-- > 0)
+ {
+ ch = *src++;
+ if (isascii(ch) && isspace(ch)) /* Skip whitespace anywhere */
+ continue;
+ if (ch == xds_pad64)
+ break;
+ pos = strchr(xds_base64, ch);
+ if (pos == 0) /* A non-base64 character */
+ return -1;
+ switch (state)
+ {
+ case 0:
+ if (dst != NULL)
+ {
+ if ((size_t)dstidx >= dstlen)
+ return -1;
+ dst[dstidx] = ((pos - xds_base64) << 2);
+ }
+ state = 1;
+ break;
+ case 1:
+ if (dst != NULL)
+ {
+ if ((size_t)dstidx >= dstlen)
+ return -1;
+ dst[dstidx] |= ((pos - xds_base64) >> 4);
+ res = (((pos - xds_base64) & 0x0f) << 4);
+ }
+ dstidx++;
+ state = 2;
+ break;
+ case 2:
+ if (dst != NULL)
+ {
+ if ((size_t)dstidx >= dstlen)
+ return -1;
+ dst[dstidx] = res | ((pos - xds_base64) >> 2);
+ res = ((pos - xds_base64) & 0x03) << 6;
+ }
+ dstidx++;
+ state = 3;
+ break;
+ case 3:
+ if (dst != NULL)
+ {
+ if ((size_t)dstidx >= dstlen)
+ return -1;
+ dst[dstidx] = res | (pos - xds_base64);
+ }
+ dstidx++;
+ state = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == xds_pad64)
+ { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state)
+ {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return -1;
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for (; ch != '\0'; ch = *src++)
+ if (!(isascii(ch) && isspace(ch)))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != xds_pad64)
+ return -1;
+ ch = *src++; /* Skip the = */
+ /* FALLTHROUGH */
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for (; ch != '\0'; ch = *src++)
+ if (!(isascii(ch) && isspace(ch)))
+ return -1;
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (dst != NULL && res != 0)
+ return -1;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return -1;
+ }
+
+ return dstidx;
+ }
+
+ int xml_decode_octetstream(xds_t* xds, void* engine_context,
+ void* buffer, size_t buffer_size, size_t* used_buffer_size,
+ va_list* args)
+ {
+ char* p;
+ size_t p_len;
+ xds_uint8_t** data;
+ size_t* data_len;
+
+ /* We need at least 27 byte for the starting and ending tag. */
+
+ xds_init_encoding_engine(13 + 14);
+
+ /* Get parameters from stack. */
+
+ data = va_arg(*args, xds_uint8_t**);
+ xds_check_parameter(data != NULL);
+ data_len = va_arg(*args, size_t*);
+
+ /* Check for the opening tag. */
+
+ if (memcmp("<octetstream>", buffer, 13) != 0)
+ return XDS_ERR_TYPE_MISMATCH;
+
+ /* Find the end of the data and calculate the length of the
+ base64-encoded stuff. */
+
+ p = (char*)buffer + 13;
+ while(p < ((char*)buffer+buffer_size) && *p != '<')
+ ++p;
+ if (p == ((char*)buffer+buffer_size))
+ return XDS_ERR_TYPE_MISMATCH;
+ else
+ {
+ p_len = p - ((char*)buffer + 13);
+ p = (char*)buffer + 13;
+ }
+
+ /* Now find out how long the decoded data is going to be and
+ allocate a buffer for it. */
+
+ p[p_len] = '\0';
+ *data_len = base64_decode(NULL, 0, p, p_len);
+ p[p_len] = '<';
+ if (*data_len == (size_t)-1)
+ return XDS_ERR_UNKNOWN;
+ *data = malloc(*data_len);
+ if (*data == NULL)
+ return XDS_ERR_NO_MEM;
+
+ /* Decode the data. */
+
+ p[p_len] = '\0';
+ base64_decode(*data, *data_len, p, p_len);
+ p[p_len] = '<';
+
+ /* Check that we have a closing tag. */
+
+ if (memcmp(p + p_len, "</octetstream>", 14) != 0)
+ {
+ free(*data);
+ return XDS_ERR_TYPE_MISMATCH;
+ }
+
+ /* Done. */
+
+ *used_buffer_size = 13 + p_len + 14;
+ return XDS_OK;
+ }
+
|