Moved chunk_t to utils folder
authorTobias Brunner <tobias@strongswan.org>
Tue, 16 Oct 2012 13:53:49 +0000 (15:53 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 24 Oct 2012 14:00:50 +0000 (16:00 +0200)
14 files changed:
src/libhydra/attributes/attribute_handler.h
src/libstrongswan/Android.mk
src/libstrongswan/Makefile.am
src/libstrongswan/chunk.c [deleted file]
src/libstrongswan/chunk.h [deleted file]
src/libstrongswan/fetcher/fetcher.h
src/libstrongswan/library.h
src/libstrongswan/networking/host.h
src/libstrongswan/plugins/agent/agent_private_key.c
src/libstrongswan/plugins/mysql/mysql_database.c
src/libstrongswan/plugins/pkcs11/pkcs11_library.h
src/libstrongswan/utils/chunk.c [new file with mode: 0644]
src/libstrongswan/utils/chunk.h [new file with mode: 0644]
src/libstrongswan/utils/identification.h

index 91fa4e5..bc488f6 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef ATTRIBUTE_HANDLER_H_
 #define ATTRIBUTE_HANDLER_H_
 
-#include <chunk.h>
+#include <utils/chunk.h>
 #include <utils/identification.h>
 #include <collections/linked_list.h>
 
index ef9f378..7308e3f 100644 (file)
@@ -3,7 +3,7 @@ include $(CLEAR_VARS)
 
 # copy-n-paste from Makefile.am
 LOCAL_SRC_FILES := \
-library.c chunk.c debug.c enum.c settings.c \
+library.c debug.c enum.c settings.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
 collections/linked_list.c \
@@ -30,7 +30,7 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
 threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
-utils.c utils/identification.c utils/lexparser.c \
+utils.c utils/chunk.c utils/identification.c utils/lexparser.c \
 utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/printf_hook.c
 
 # adding the plugin source files
index 77120c6..07d04b0 100644 (file)
@@ -1,7 +1,7 @@
 ipseclib_LTLIBRARIES = libstrongswan.la
 
 libstrongswan_la_SOURCES = \
-library.c chunk.c debug.c enum.c settings.c \
+library.c debug.c enum.c settings.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
 collections/linked_list.c \
@@ -28,13 +28,13 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
 threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
-utils.c utils/identification.c utils/lexparser.c \
+utils.c utils/chunk.c utils/identification.c utils/lexparser.c \
 utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/printf_hook.c
 
 if USE_DEV_HEADERS
 strongswan_includedir = ${dev_headers}
 nobase_strongswan_include_HEADERS = \
-library.h chunk.h debug.h enum.h settings.h \
+library.h debug.h enum.h settings.h \
 asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
 collections/linked_list.h \
@@ -68,7 +68,7 @@ processing/scheduler.h selectors/traffic_selector.h \
 threading/thread.h threading/thread_value.h \
 threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
 threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
-utils.h utils/identification.h utils/lexparser.h \
+utils.h utils/chunk.h utils/identification.h utils/lexparser.h \
 utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
 utils/leak_detective.h utils/printf_hook.h utils/integrity_checker.h
 endif
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
deleted file mode 100644 (file)
index d7f1c31..0000000
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "chunk.h"
-#include "debug.h"
-
-/* required for chunk_hash */
-#undef get16bits
-#if (defined(__GNUC__) && defined(__i386__))
-#define get16bits(d) (*((const u_int16_t*)(d)))
-#endif
-#if !defined (get16bits)
-#define get16bits(d) ((((u_int32_t)(((const u_int8_t*)(d))[1])) << 8)\
-                      + (u_int32_t)(((const u_int8_t*)(d))[0]) )
-#endif
-
-/**
- * Empty chunk.
- */
-chunk_t chunk_empty = { NULL, 0 };
-
-/**
- * Described in header.
- */
-chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
-{
-       chunk_t clone = chunk_empty;
-
-       if (chunk.ptr && chunk.len > 0)
-       {
-               clone.ptr = ptr;
-               clone.len = chunk.len;
-               memcpy(clone.ptr, chunk.ptr, chunk.len);
-       }
-
-       return clone;
-}
-
-/**
- * Described in header.
- */
-size_t chunk_length(const char* mode, ...)
-{
-       va_list chunks;
-       size_t length = 0;
-
-       va_start(chunks, mode);
-       while (TRUE)
-       {
-               switch (*mode++)
-               {
-                       case 'm':
-                       case 'c':
-                       case 's':
-                       {
-                               chunk_t ch = va_arg(chunks, chunk_t);
-                               length += ch.len;
-                               continue;
-                       }
-                       default:
-                               break;
-               }
-               break;
-       }
-       va_end(chunks);
-       return length;
-}
-
-/**
- * Described in header.
- */
-chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
-{
-       va_list chunks;
-       chunk_t construct = chunk_create(ptr, 0);
-
-       va_start(chunks, mode);
-       while (TRUE)
-       {
-               bool free_chunk = FALSE, clear_chunk = FALSE;
-               chunk_t ch;
-
-               switch (*mode++)
-               {
-                       case 's':
-                               clear_chunk = TRUE;
-                               /* FALL */
-                       case 'm':
-                               free_chunk = TRUE;
-                               /* FALL */
-                       case 'c':
-                               ch = va_arg(chunks, chunk_t);
-                               memcpy(ptr, ch.ptr, ch.len);
-                               ptr += ch.len;
-                               construct.len += ch.len;
-                               if (clear_chunk)
-                               {
-                                       chunk_clear(&ch);
-                               }
-                               else if (free_chunk)
-                               {
-                                       free(ch.ptr);
-                               }
-                               continue;
-                       default:
-                               break;
-               }
-               break;
-       }
-       va_end(chunks);
-
-       return construct;
-}
-
-/**
- * Described in header.
- */
-void chunk_split(chunk_t chunk, const char *mode, ...)
-{
-       va_list chunks;
-       u_int len;
-       chunk_t *ch;
-
-       va_start(chunks, mode);
-       while (TRUE)
-       {
-               if (*mode == '\0')
-               {
-                       break;
-               }
-               len = va_arg(chunks, u_int);
-               ch = va_arg(chunks, chunk_t*);
-               /* a null chunk means skip len bytes */
-               if (ch == NULL)
-               {
-                       chunk = chunk_skip(chunk, len);
-                       continue;
-               }
-               switch (*mode++)
-               {
-                       case 'm':
-                       {
-                               ch->len = min(chunk.len, len);
-                               if (ch->len)
-                               {
-                                       ch->ptr = chunk.ptr;
-                               }
-                               else
-                               {
-                                       ch->ptr = NULL;
-                               }
-                               chunk = chunk_skip(chunk, ch->len);
-                               continue;
-                       }
-                       case 'a':
-                       {
-                               ch->len = min(chunk.len, len);
-                               if (ch->len)
-                               {
-                                       ch->ptr = malloc(ch->len);
-                                       memcpy(ch->ptr, chunk.ptr, ch->len);
-                               }
-                               else
-                               {
-                                       ch->ptr = NULL;
-                               }
-                               chunk = chunk_skip(chunk, ch->len);
-                               continue;
-                       }
-                       case 'c':
-                       {
-                               ch->len = min(ch->len, chunk.len);
-                               ch->len = min(ch->len, len);
-                               if (ch->len)
-                               {
-                                       memcpy(ch->ptr, chunk.ptr, ch->len);
-                               }
-                               else
-                               {
-                                       ch->ptr = NULL;
-                               }
-                               chunk = chunk_skip(chunk, ch->len);
-                               continue;
-                       }
-                       default:
-                               break;
-               }
-               break;
-       }
-       va_end(chunks);
-}
-
-/**
- * Described in header.
- */
-bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force)
-{
-       mode_t oldmask;
-       FILE *fd;
-       bool good = FALSE;
-
-       if (!force && access(path, F_OK) == 0)
-       {
-               DBG1(DBG_LIB, "  %s file '%s' already exists", label, path);
-               return FALSE;
-       }
-       oldmask = umask(mask);
-       fd = fopen(path, "w");
-       if (fd)
-       {
-               if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
-               {
-                       DBG1(DBG_LIB, "  written %s file '%s' (%d bytes)",
-                                label, path, chunk.len);
-                       good = TRUE;
-               }
-               else
-               {
-                       DBG1(DBG_LIB, "  writing %s file '%s' failed: %s",
-                                label, path, strerror(errno));
-               }
-               fclose(fd);
-       }
-       else
-       {
-               DBG1(DBG_LIB, "  could not open %s file '%s': %s", label, path,
-                        strerror(errno));
-       }
-       umask(oldmask);
-       return good;
-}
-
-
-/** hex conversion digits */
-static char hexdig_upper[] = "0123456789ABCDEF";
-static char hexdig_lower[] = "0123456789abcdef";
-
-/**
- * Described in header.
- */
-chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase)
-{
-       int i, len;
-       char *hexdig = hexdig_lower;
-
-       if (uppercase)
-       {
-               hexdig = hexdig_upper;
-       }
-
-       len = chunk.len * 2;
-       if (!buf)
-       {
-               buf = malloc(len + 1);
-       }
-       buf[len] = '\0';
-
-       for (i = 0; i < chunk.len; i++)
-       {
-               buf[i*2]   = hexdig[(chunk.ptr[i] >> 4) & 0xF];
-               buf[i*2+1] = hexdig[(chunk.ptr[i]     ) & 0xF];
-       }
-       return chunk_create(buf, len);
-}
-
-/**
- * convert a signle hex character to its binary value
- */
-static char hex2bin(char hex)
-{
-       switch (hex)
-       {
-               case '0' ... '9':
-                       return hex - '0';
-               case 'A' ... 'F':
-                       return hex - 'A' + 10;
-               case 'a' ... 'f':
-                       return hex - 'a' + 10;
-               default:
-                       return 0;
-       }
-}
-
-/**
- * Described in header.
- */
-chunk_t chunk_from_hex(chunk_t hex, char *buf)
-{
-       int i, len;
-       u_char *ptr;
-       bool odd = FALSE;
-
-   /* subtract the number of optional ':' separation characters */
-       len = hex.len;
-       ptr = hex.ptr;
-       for (i = 0; i < hex.len; i++)
-       {
-               if (*ptr++ == ':')
-               {
-                       len--;
-               }
-       }
-
-       /* compute the number of binary bytes */
-       if (len % 2)
-       {
-               odd = TRUE;
-               len++;
-       }
-       len /= 2;
-
-       /* allocate buffer memory unless provided by caller */
-       if (!buf)
-       {
-               buf = malloc(len);
-       }
-
-       /* buffer is filled from the right */
-       memset(buf, 0, len);
-       hex.ptr += hex.len;
-
-       for (i = len - 1; i >= 0; i--)
-       {
-               /* skip separation characters */
-               if (*(--hex.ptr) == ':')
-               {
-                       --hex.ptr;
-               }
-               buf[i] = hex2bin(*hex.ptr);
-               if (i > 0 || !odd)
-               {
-                       buf[i] |= hex2bin(*(--hex.ptr)) << 4;
-               }
-       }
-       return chunk_create(buf, len);
-}
-
-/** base 64 conversion digits */
-static char b64digits[] =
-       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/**
- * Described in header.
- */
-chunk_t chunk_to_base64(chunk_t chunk, char *buf)
-{
-       int i, len;
-       char *pos;
-
-       len = chunk.len + ((3 - chunk.len % 3) % 3);
-       if (!buf)
-       {
-               buf = malloc(len * 4 / 3 + 1);
-       }
-       pos = buf;
-       for (i = 0; i < len; i+=3)
-       {
-               *pos++ = b64digits[chunk.ptr[i] >> 2];
-               if (i+1 >= chunk.len)
-               {
-                       *pos++ = b64digits[(chunk.ptr[i] & 0x03) << 4];
-                       *pos++ = '=';
-                       *pos++ = '=';
-                       break;
-               }
-               *pos++ = b64digits[((chunk.ptr[i] & 0x03) << 4) | (chunk.ptr[i+1] >> 4)];
-               if (i+2 >= chunk.len)
-               {
-                       *pos++ = b64digits[(chunk.ptr[i+1] & 0x0F) << 2];
-                       *pos++ = '=';
-                       break;
-               }
-               *pos++ = b64digits[((chunk.ptr[i+1] & 0x0F) << 2) | (chunk.ptr[i+2] >> 6)];
-               *pos++ = b64digits[chunk.ptr[i+2] & 0x3F];
-       }
-       *pos = '\0';
-       return chunk_create(buf, len * 4 / 3);
-}
-
-/**
- * convert a base 64 digit to its binary form (inversion of b64digits array)
- */
-static int b642bin(char b64)
-{
-       switch (b64)
-       {
-               case 'A' ... 'Z':
-                       return b64 - 'A';
-               case 'a' ... 'z':
-                       return ('Z' - 'A' + 1) + b64 - 'a';
-               case '0' ... '9':
-                       return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64 - '0';
-               case '+':
-               case '-':
-                       return 62;
-               case '/':
-               case '_':
-                       return 63;
-               case '=':
-                       return 0;
-               default:
-                       return -1;
-       }
-}
-
-/**
- * Described in header.
- */
-chunk_t chunk_from_base64(chunk_t base64, char *buf)
-{
-       u_char *pos, byte[4];
-       int i, j, len, outlen;
-
-       len = base64.len / 4 * 3;
-       if (!buf)
-       {
-               buf = malloc(len);
-       }
-       pos = base64.ptr;
-       outlen = 0;
-       for (i = 0; i < len; i+=3)
-       {
-               outlen += 3;
-               for (j = 0; j < 4; j++)
-               {
-                       if (*pos == '=')
-                       {
-                               outlen--;
-                       }
-                       byte[j] = b642bin(*pos++);
-               }
-               buf[i] = (byte[0] << 2) | (byte[1] >> 4);
-               buf[i+1] = (byte[1] << 4) | (byte[2] >> 2);
-               buf[i+2] = (byte[2] << 6) | (byte[3]);
-       }
-       return chunk_create(buf, outlen);
-}
-
-/** base 32 conversion digits */
-static char b32digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
-
-/**
- * Described in header.
- */
-chunk_t chunk_to_base32(chunk_t chunk, char *buf)
-{
-       int i, len;
-       char *pos;
-
-       len = chunk.len + ((5 - chunk.len % 5) % 5);
-       if (!buf)
-       {
-               buf = malloc(len * 8 / 5 + 1);
-       }
-       pos = buf;
-       for (i = 0; i < len; i+=5)
-       {
-               *pos++ = b32digits[chunk.ptr[i] >> 3];
-               if (i+1 >= chunk.len)
-               {
-                       *pos++ = b32digits[(chunk.ptr[i] & 0x07) << 2];
-                       memset(pos, '=', 6);
-                       pos += 6;
-                       break;
-               }
-               *pos++ = b32digits[((chunk.ptr[i] & 0x07) << 2) |
-                                                  (chunk.ptr[i+1] >> 6)];
-               *pos++ = b32digits[(chunk.ptr[i+1] & 0x3E) >> 1];
-               if (i+2 >= chunk.len)
-               {
-                       *pos++ = b32digits[(chunk.ptr[i+1] & 0x01) << 4];
-                       memset(pos, '=', 4);
-                       pos += 4;
-                       break;
-               }
-               *pos++ = b32digits[((chunk.ptr[i+1] & 0x01) << 4) |
-                                                  (chunk.ptr[i+2] >> 4)];
-               if (i+3 >= chunk.len)
-               {
-                       *pos++ = b32digits[(chunk.ptr[i+2] & 0x0F) << 1];
-                       memset(pos, '=', 3);
-                       pos += 3;
-                       break;
-               }
-               *pos++ = b32digits[((chunk.ptr[i+2] & 0x0F) << 1) |
-                                                  (chunk.ptr[i+3] >> 7)];
-               *pos++ = b32digits[(chunk.ptr[i+3] & 0x7F) >> 2];
-               if (i+4 >= chunk.len)
-               {
-                       *pos++ = b32digits[(chunk.ptr[i+3] & 0x03) << 3];
-                       *pos++ = '=';
-                       break;
-               }
-               *pos++ = b32digits[((chunk.ptr[i+3] & 0x03) << 3) |
-                                                  (chunk.ptr[i+4] >> 5)];
-               *pos++ = b32digits[chunk.ptr[i+4] & 0x1F];
-       }
-       *pos = '\0';
-       return chunk_create(buf, len * 8 / 5);
-}
-
-/**
- * Described in header.
- */
-int chunk_compare(chunk_t a, chunk_t b)
-{
-       int compare_len = a.len - b.len;
-       int len = (compare_len < 0)? a.len : b.len;
-
-       if (compare_len != 0 || len == 0)
-       {
-               return compare_len;
-       }
-       return memcmp(a.ptr, b.ptr, len);
-};
-
-
-/**
- * Described in header.
- */
-bool chunk_increment(chunk_t chunk)
-{
-       int i;
-
-       for (i = chunk.len - 1; i >= 0; i--)
-       {
-               if (++chunk.ptr[i] != 0)
-               {
-                       return FALSE;
-               }
-       }
-       return TRUE;
-}
-
-/**
- * Remove non-printable characters from a chunk.
- */
-bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace)
-{
-       bool printable = TRUE;
-       int i;
-
-       if (sane)
-       {
-               *sane = chunk_clone(chunk);
-       }
-       for (i = 0; i < chunk.len; i++)
-       {
-               if (!isprint(chunk.ptr[i]))
-               {
-                       if (sane)
-                       {
-                               sane->ptr[i] = replace;
-                       }
-                       printable = FALSE;
-               }
-       }
-       return printable;
-}
-
-/**
- * Described in header.
- *
- * The implementation is based on Paul Hsieh's SuperFastHash:
- *      http://www.azillionmonkeys.com/qed/hash.html
- */
-u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
-{
-       u_char *data = chunk.ptr;
-       size_t len = chunk.len;
-       u_int32_t tmp;
-       int rem;
-
-       if (!len || data == NULL)
-       {
-               return 0;
-       }
-
-       rem = len & 3;
-       len >>= 2;
-
-       /* Main loop */
-       for (; len > 0; --len)
-       {
-               hash += get16bits(data);
-               tmp   = (get16bits(data + 2) << 11) ^ hash;
-               hash  = (hash << 16) ^ tmp;
-               data += 2 * sizeof(u_int16_t);
-               hash += hash >> 11;
-       }
-
-       /* Handle end cases */
-       switch (rem)
-       {
-               case 3:
-               {
-                       hash += get16bits(data);
-                       hash ^= hash << 16;
-                       hash ^= data[sizeof(u_int16_t)] << 18;
-                       hash += hash >> 11;
-                       break;
-               }
-               case 2:
-               {
-                       hash += get16bits(data);
-                       hash ^= hash << 11;
-                       hash += hash >> 17;
-                       break;
-               }
-               case 1:
-               {
-                       hash += *data;
-                       hash ^= hash << 10;
-                       hash += hash >> 1;
-                       break;
-               }
-       }
-
-       /* Force "avalanching" of final 127 bits */
-       hash ^= hash << 3;
-       hash += hash >> 5;
-       hash ^= hash << 4;
-       hash += hash >> 17;
-       hash ^= hash << 25;
-       hash += hash >> 6;
-
-       return hash;
-}
-
-/**
- * Described in header.
- */
-u_int32_t chunk_hash(chunk_t chunk)
-{
-       return chunk_hash_inc(chunk, chunk.len);
-}
-
-/**
- * Described in header.
- */
-int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-                                         const void *const *args)
-{
-       chunk_t *chunk = *((chunk_t**)(args[0]));
-       bool first = TRUE;
-       chunk_t copy = *chunk;
-       int written = 0;
-
-       if (!spec->hash)
-       {
-               u_int chunk_len = chunk->len;
-               const void *new_args[] = {&chunk->ptr, &chunk_len};
-               return mem_printf_hook(data, spec, new_args);
-       }
-
-       while (copy.len > 0)
-       {
-               if (first)
-               {
-                       first = FALSE;
-               }
-               else
-               {
-                       written += print_in_hook(data, ":");
-               }
-               written += print_in_hook(data, "%02x", *copy.ptr++);
-               copy.len--;
-       }
-       return written;
-}
diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h
deleted file mode 100644 (file)
index 91b23da..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup chunk chunk
- * @{ @ingroup libstrongswan
- */
-
-#ifndef CHUNK_H_
-#define CHUNK_H_
-
-#include <string.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-typedef struct chunk_t chunk_t;
-
-/**
- * General purpose pointer/length abstraction.
- */
-struct chunk_t {
-       /** Pointer to start of data */
-       u_char *ptr;
-       /** Length of data in bytes */
-       size_t len;
-};
-
-#include "utils.h"
-
-/**
- * A { NULL, 0 }-chunk handy for initialization.
- */
-extern chunk_t chunk_empty;
-
-/**
- * Create a new chunk pointing to "ptr" with length "len"
- */
-static inline chunk_t chunk_create(u_char *ptr, size_t len)
-{
-       chunk_t chunk = {ptr, len};
-       return chunk;
-}
-
-/**
- * Create a clone of a chunk pointing to "ptr"
- */
-chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
-
-/**
- * Calculate length of multiple chunks
- */
-size_t chunk_length(const char *mode, ...);
-
-/**
- * Concatenate chunks into a chunk pointing to "ptr".
- *
- * The mode string specifies the number of chunks, and how to handle each of
- * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
- * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
- */
-chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
-
-/**
- * Split up a chunk into parts, "mode" is a string of "a" (alloc),
- * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
- * it should get allocated on heap, copied into existing chunk, or the chunk
- * should point into "chunk". The length of each part is an argument before
- * each target chunk. E.g.:
- * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
- */
-void chunk_split(chunk_t chunk, const char *mode, ...);
-
-/**
- * Write the binary contents of a chunk_t to a file
- *
- * @param chunk                        contents to write to file
- * @param path                 path where file is written to
- * @param label                        label specifying file type
- * @param mask                 file mode creation mask
- * @param force                        overwrite existing file by force
- * @return                             TRUE if write operation was successful
- */
-bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force);
-
-/**
- * Convert a chunk of data to hex encoding.
- *
- * The resulting string is '\\0' terminated, but the chunk does not include
- * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
- *
- * @param chunk                        data to convert to hex encoding
- * @param buf                  buffer to write to, NULL to malloc
- * @param uppercase            TRUE to use uppercase letters
- * @return                             chunk of encoded data
- */
-chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
-
-/**
- * Convert a hex encoded in a binary chunk.
- *
- * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
- * bytes. It is filled by the right to give correct values for short inputs.
- *
- * @param hex                  hex encoded input data
- * @param buf                  buffer to write decoded data, NULL to malloc
- * @return                             converted data
- */
-chunk_t chunk_from_hex(chunk_t hex, char *buf);
-
-/**
- * Convert a chunk of data to its base64 encoding.
- *
- * The resulting string is '\\0' terminated, but the chunk does not include
- * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
- *
- * @param chunk                        data to convert
- * @param buf                  buffer to write to, NULL to malloc
- * @return                             chunk of encoded data
- */
-chunk_t chunk_to_base64(chunk_t chunk, char *buf);
-
-/**
- * Convert a base64 in a binary chunk.
- *
- * If buf is supplied, it must hold at least (base64.len / 4 * 3).
- *
- * @param base64               base64 encoded input data
- * @param buf                  buffer to write decoded data, NULL to malloc
- * @return                             converted data
- */
-chunk_t chunk_from_base64(chunk_t base64, char *buf);
-
-/**
- * Convert a chunk of data to its base32 encoding.
- *
- * The resulting string is '\\0' terminated, but the chunk does not include
- * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
- *
- * @param chunk                        data to convert
- * @param buf                  buffer to write to, NULL to malloc
- * @return                             chunk of encoded data
- */
-chunk_t chunk_to_base32(chunk_t chunk, char *buf);
-
-/**
- * Free contents of a chunk
- */
-static inline void chunk_free(chunk_t *chunk)
-{
-       free(chunk->ptr);
-       *chunk = chunk_empty;
-}
-
-/**
- * Overwrite the contents of a chunk and free it
- */
-static inline void chunk_clear(chunk_t *chunk)
-{
-       if (chunk->ptr)
-       {
-               memwipe(chunk->ptr, chunk->len);
-               chunk_free(chunk);
-       }
-}
-
-/**
- * Initialize a chunk using a char array
- */
-#define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})})
-
-/**
- * Initialize a chunk to point to a thing
- */
-#define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing))
-
-/**
- * Allocate a chunk on the heap
- */
-#define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
-
-/**
- * Allocate a chunk on the stack
- */
-#define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
-
-/**
- * Clone a chunk on heap
- */
-#define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
-
-/**
- * Clone a chunk on stack
- */
-#define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
-
-/**
- * Concatenate chunks into a chunk on heap
- */
-#define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
-
-/**
- * Concatenate chunks into a chunk on stack
- */
-#define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
-
-/**
- * Skip n bytes in chunk (forward pointer, shorten length)
- */
-static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
-{
-       if (chunk.len > bytes)
-       {
-               chunk.ptr += bytes;
-               chunk.len -= bytes;
-               return chunk;
-       }
-       return chunk_empty;
-}
-
-/**
- * Skip a leading zero-valued byte
- */
-static inline chunk_t chunk_skip_zero(chunk_t chunk)
-{
-       if (chunk.len > 1 && *chunk.ptr == 0x00)
-       {
-               chunk.ptr++;
-               chunk.len--;
-       }
-       return chunk;
-}
-
-
-/**
- *  Compare two chunks, returns zero if a equals b
- *  or negative/positive if a is small/greater than b
- */
-int chunk_compare(chunk_t a, chunk_t b);
-
-/**
- * Compare two chunks for equality,
- * NULL chunks are never equal.
- */
-static inline bool chunk_equals(chunk_t a, chunk_t b)
-{
-       return a.ptr != NULL  && b.ptr != NULL &&
-                       a.len == b.len && memeq(a.ptr, b.ptr, a.len);
-}
-
-/**
- * Compare two chunks (given as pointers) for equality (useful as callback),
- * NULL chunks are never equal.
- */
-static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
-{
-       return a != NULL && b != NULL && chunk_equals(*a, *b);
-}
-
-/**
- * Increment a chunk, as it would reprensent a network order integer.
- *
- * @param chunk                        chunk to increment
- * @return                             TRUE if an overflow occurred
- */
-bool chunk_increment(chunk_t chunk);
-
-/**
- * Check if a chunk has printable characters only.
- *
- * If sane is given, chunk is cloned into sane and all non printable characters
- * get replaced by "replace".
- *
- * @param chunk                        chunk to check for printability
- * @param sane                 pointer where sane version is allocated, or NULL
- * @param replace              character to use for replaceing unprintable characters
- * @return                             TRUE if all characters in chunk are printable
- */
-bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
-
-/**
- * Computes a 32 bit hash of the given chunk.
- * Note: This hash is only intended for hash tables not for cryptographic purposes.
- */
-u_int32_t chunk_hash(chunk_t chunk);
-
-/**
- * Incremental version of chunk_hash. Use this to hash two or more chunks.
- */
-u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
-
-/**
- * printf hook function for chunk_t.
- *
- * Arguments are:
- *     chunk_t *chunk
- * Use #-modifier to print a compact version
- */
-int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-                                         const void *const *args);
-
-#endif /** CHUNK_H_ @}*/
index 5b734da..58451ae 100644 (file)
@@ -26,7 +26,7 @@ typedef struct fetcher_t fetcher_t;
 typedef enum fetcher_option_t fetcher_option_t;
 
 #include <stdarg.h>
-#include <chunk.h>
+#include <utils/chunk.h>
 
 /**
  * Constructor function which creates fetcher instances.
index c8e8827..699d5cb 100644 (file)
@@ -83,7 +83,6 @@
 /* make sure we include printf_hook.h first */
 #include "utils/printf_hook.h"
 #include "utils.h"
-#include "chunk.h"
 #include "settings.h"
 #include "networking/host_resolver.h"
 #include "processing/processor.h"
@@ -95,6 +94,7 @@
 #include "credentials/credential_factory.h"
 #include "credentials/credential_manager.h"
 #include "credentials/cred_encoding.h"
+#include "utils/chunk.h"
 #include "utils/integrity_checker.h"
 #include "utils/leak_detective.h"
 #include "plugins/plugin_loader.h"
index cae2a4f..1c49b1a 100644 (file)
@@ -34,7 +34,7 @@ typedef struct host_t host_t;
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <chunk.h>
+#include <utils/chunk.h>
 
 /**
  * Differences between two hosts. They differ in
index 60b57ad..8d49431 100644 (file)
@@ -24,7 +24,7 @@
 #include <errno.h>
 
 #include <library.h>
-#include <chunk.h>
+#include <utils/chunk.h>
 #include <debug.h>
 
 #ifndef UNIX_PATH_MAX
index 12a8ff5..d31e1eb 100644 (file)
@@ -20,7 +20,7 @@
 #include "mysql_database.h"
 
 #include <debug.h>
-#include <chunk.h>
+#include <utils/chunk.h>
 #include <threading/thread_value.h>
 #include <threading/mutex.h>
 #include <collections/linked_list.h>
index 81414a2..f225b9b 100644 (file)
@@ -30,7 +30,7 @@ typedef struct pkcs11_library_t pkcs11_library_t;
 #include "pkcs11.h"
 
 #include <enum.h>
-#include <chunk.h>
+#include <utils/chunk.h>
 #include <collections/enumerator.h>
 
 /**
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
new file mode 100644 (file)
index 0000000..d7f1c31
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "chunk.h"
+#include "debug.h"
+
+/* required for chunk_hash */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__))
+#define get16bits(d) (*((const u_int16_t*)(d)))
+#endif
+#if !defined (get16bits)
+#define get16bits(d) ((((u_int32_t)(((const u_int8_t*)(d))[1])) << 8)\
+                      + (u_int32_t)(((const u_int8_t*)(d))[0]) )
+#endif
+
+/**
+ * Empty chunk.
+ */
+chunk_t chunk_empty = { NULL, 0 };
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
+{
+       chunk_t clone = chunk_empty;
+
+       if (chunk.ptr && chunk.len > 0)
+       {
+               clone.ptr = ptr;
+               clone.len = chunk.len;
+               memcpy(clone.ptr, chunk.ptr, chunk.len);
+       }
+
+       return clone;
+}
+
+/**
+ * Described in header.
+ */
+size_t chunk_length(const char* mode, ...)
+{
+       va_list chunks;
+       size_t length = 0;
+
+       va_start(chunks, mode);
+       while (TRUE)
+       {
+               switch (*mode++)
+               {
+                       case 'm':
+                       case 'c':
+                       case 's':
+                       {
+                               chunk_t ch = va_arg(chunks, chunk_t);
+                               length += ch.len;
+                               continue;
+                       }
+                       default:
+                               break;
+               }
+               break;
+       }
+       va_end(chunks);
+       return length;
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
+{
+       va_list chunks;
+       chunk_t construct = chunk_create(ptr, 0);
+
+       va_start(chunks, mode);
+       while (TRUE)
+       {
+               bool free_chunk = FALSE, clear_chunk = FALSE;
+               chunk_t ch;
+
+               switch (*mode++)
+               {
+                       case 's':
+                               clear_chunk = TRUE;
+                               /* FALL */
+                       case 'm':
+                               free_chunk = TRUE;
+                               /* FALL */
+                       case 'c':
+                               ch = va_arg(chunks, chunk_t);
+                               memcpy(ptr, ch.ptr, ch.len);
+                               ptr += ch.len;
+                               construct.len += ch.len;
+                               if (clear_chunk)
+                               {
+                                       chunk_clear(&ch);
+                               }
+                               else if (free_chunk)
+                               {
+                                       free(ch.ptr);
+                               }
+                               continue;
+                       default:
+                               break;
+               }
+               break;
+       }
+       va_end(chunks);
+
+       return construct;
+}
+
+/**
+ * Described in header.
+ */
+void chunk_split(chunk_t chunk, const char *mode, ...)
+{
+       va_list chunks;
+       u_int len;
+       chunk_t *ch;
+
+       va_start(chunks, mode);
+       while (TRUE)
+       {
+               if (*mode == '\0')
+               {
+                       break;
+               }
+               len = va_arg(chunks, u_int);
+               ch = va_arg(chunks, chunk_t*);
+               /* a null chunk means skip len bytes */
+               if (ch == NULL)
+               {
+                       chunk = chunk_skip(chunk, len);
+                       continue;
+               }
+               switch (*mode++)
+               {
+                       case 'm':
+                       {
+                               ch->len = min(chunk.len, len);
+                               if (ch->len)
+                               {
+                                       ch->ptr = chunk.ptr;
+                               }
+                               else
+                               {
+                                       ch->ptr = NULL;
+                               }
+                               chunk = chunk_skip(chunk, ch->len);
+                               continue;
+                       }
+                       case 'a':
+                       {
+                               ch->len = min(chunk.len, len);
+                               if (ch->len)
+                               {
+                                       ch->ptr = malloc(ch->len);
+                                       memcpy(ch->ptr, chunk.ptr, ch->len);
+                               }
+                               else
+                               {
+                                       ch->ptr = NULL;
+                               }
+                               chunk = chunk_skip(chunk, ch->len);
+                               continue;
+                       }
+                       case 'c':
+                       {
+                               ch->len = min(ch->len, chunk.len);
+                               ch->len = min(ch->len, len);
+                               if (ch->len)
+                               {
+                                       memcpy(ch->ptr, chunk.ptr, ch->len);
+                               }
+                               else
+                               {
+                                       ch->ptr = NULL;
+                               }
+                               chunk = chunk_skip(chunk, ch->len);
+                               continue;
+                       }
+                       default:
+                               break;
+               }
+               break;
+       }
+       va_end(chunks);
+}
+
+/**
+ * Described in header.
+ */
+bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force)
+{
+       mode_t oldmask;
+       FILE *fd;
+       bool good = FALSE;
+
+       if (!force && access(path, F_OK) == 0)
+       {
+               DBG1(DBG_LIB, "  %s file '%s' already exists", label, path);
+               return FALSE;
+       }
+       oldmask = umask(mask);
+       fd = fopen(path, "w");
+       if (fd)
+       {
+               if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
+               {
+                       DBG1(DBG_LIB, "  written %s file '%s' (%d bytes)",
+                                label, path, chunk.len);
+                       good = TRUE;
+               }
+               else
+               {
+                       DBG1(DBG_LIB, "  writing %s file '%s' failed: %s",
+                                label, path, strerror(errno));
+               }
+               fclose(fd);
+       }
+       else
+       {
+               DBG1(DBG_LIB, "  could not open %s file '%s': %s", label, path,
+                        strerror(errno));
+       }
+       umask(oldmask);
+       return good;
+}
+
+
+/** hex conversion digits */
+static char hexdig_upper[] = "0123456789ABCDEF";
+static char hexdig_lower[] = "0123456789abcdef";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase)
+{
+       int i, len;
+       char *hexdig = hexdig_lower;
+
+       if (uppercase)
+       {
+               hexdig = hexdig_upper;
+       }
+
+       len = chunk.len * 2;
+       if (!buf)
+       {
+               buf = malloc(len + 1);
+       }
+       buf[len] = '\0';
+
+       for (i = 0; i < chunk.len; i++)
+       {
+               buf[i*2]   = hexdig[(chunk.ptr[i] >> 4) & 0xF];
+               buf[i*2+1] = hexdig[(chunk.ptr[i]     ) & 0xF];
+       }
+       return chunk_create(buf, len);
+}
+
+/**
+ * convert a signle hex character to its binary value
+ */
+static char hex2bin(char hex)
+{
+       switch (hex)
+       {
+               case '0' ... '9':
+                       return hex - '0';
+               case 'A' ... 'F':
+                       return hex - 'A' + 10;
+               case 'a' ... 'f':
+                       return hex - 'a' + 10;
+               default:
+                       return 0;
+       }
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_from_hex(chunk_t hex, char *buf)
+{
+       int i, len;
+       u_char *ptr;
+       bool odd = FALSE;
+
+   /* subtract the number of optional ':' separation characters */
+       len = hex.len;
+       ptr = hex.ptr;
+       for (i = 0; i < hex.len; i++)
+       {
+               if (*ptr++ == ':')
+               {
+                       len--;
+               }
+       }
+
+       /* compute the number of binary bytes */
+       if (len % 2)
+       {
+               odd = TRUE;
+               len++;
+       }
+       len /= 2;
+
+       /* allocate buffer memory unless provided by caller */
+       if (!buf)
+       {
+               buf = malloc(len);
+       }
+
+       /* buffer is filled from the right */
+       memset(buf, 0, len);
+       hex.ptr += hex.len;
+
+       for (i = len - 1; i >= 0; i--)
+       {
+               /* skip separation characters */
+               if (*(--hex.ptr) == ':')
+               {
+                       --hex.ptr;
+               }
+               buf[i] = hex2bin(*hex.ptr);
+               if (i > 0 || !odd)
+               {
+                       buf[i] |= hex2bin(*(--hex.ptr)) << 4;
+               }
+       }
+       return chunk_create(buf, len);
+}
+
+/** base 64 conversion digits */
+static char b64digits[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_base64(chunk_t chunk, char *buf)
+{
+       int i, len;
+       char *pos;
+
+       len = chunk.len + ((3 - chunk.len % 3) % 3);
+       if (!buf)
+       {
+               buf = malloc(len * 4 / 3 + 1);
+       }
+       pos = buf;
+       for (i = 0; i < len; i+=3)
+       {
+               *pos++ = b64digits[chunk.ptr[i] >> 2];
+               if (i+1 >= chunk.len)
+               {
+                       *pos++ = b64digits[(chunk.ptr[i] & 0x03) << 4];
+                       *pos++ = '=';
+                       *pos++ = '=';
+                       break;
+               }
+               *pos++ = b64digits[((chunk.ptr[i] & 0x03) << 4) | (chunk.ptr[i+1] >> 4)];
+               if (i+2 >= chunk.len)
+               {
+                       *pos++ = b64digits[(chunk.ptr[i+1] & 0x0F) << 2];
+                       *pos++ = '=';
+                       break;
+               }
+               *pos++ = b64digits[((chunk.ptr[i+1] & 0x0F) << 2) | (chunk.ptr[i+2] >> 6)];
+               *pos++ = b64digits[chunk.ptr[i+2] & 0x3F];
+       }
+       *pos = '\0';
+       return chunk_create(buf, len * 4 / 3);
+}
+
+/**
+ * convert a base 64 digit to its binary form (inversion of b64digits array)
+ */
+static int b642bin(char b64)
+{
+       switch (b64)
+       {
+               case 'A' ... 'Z':
+                       return b64 - 'A';
+               case 'a' ... 'z':
+                       return ('Z' - 'A' + 1) + b64 - 'a';
+               case '0' ... '9':
+                       return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64 - '0';
+               case '+':
+               case '-':
+                       return 62;
+               case '/':
+               case '_':
+                       return 63;
+               case '=':
+                       return 0;
+               default:
+                       return -1;
+       }
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_from_base64(chunk_t base64, char *buf)
+{
+       u_char *pos, byte[4];
+       int i, j, len, outlen;
+
+       len = base64.len / 4 * 3;
+       if (!buf)
+       {
+               buf = malloc(len);
+       }
+       pos = base64.ptr;
+       outlen = 0;
+       for (i = 0; i < len; i+=3)
+       {
+               outlen += 3;
+               for (j = 0; j < 4; j++)
+               {
+                       if (*pos == '=')
+                       {
+                               outlen--;
+                       }
+                       byte[j] = b642bin(*pos++);
+               }
+               buf[i] = (byte[0] << 2) | (byte[1] >> 4);
+               buf[i+1] = (byte[1] << 4) | (byte[2] >> 2);
+               buf[i+2] = (byte[2] << 6) | (byte[3]);
+       }
+       return chunk_create(buf, outlen);
+}
+
+/** base 32 conversion digits */
+static char b32digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf)
+{
+       int i, len;
+       char *pos;
+
+       len = chunk.len + ((5 - chunk.len % 5) % 5);
+       if (!buf)
+       {
+               buf = malloc(len * 8 / 5 + 1);
+       }
+       pos = buf;
+       for (i = 0; i < len; i+=5)
+       {
+               *pos++ = b32digits[chunk.ptr[i] >> 3];
+               if (i+1 >= chunk.len)
+               {
+                       *pos++ = b32digits[(chunk.ptr[i] & 0x07) << 2];
+                       memset(pos, '=', 6);
+                       pos += 6;
+                       break;
+               }
+               *pos++ = b32digits[((chunk.ptr[i] & 0x07) << 2) |
+                                                  (chunk.ptr[i+1] >> 6)];
+               *pos++ = b32digits[(chunk.ptr[i+1] & 0x3E) >> 1];
+               if (i+2 >= chunk.len)
+               {
+                       *pos++ = b32digits[(chunk.ptr[i+1] & 0x01) << 4];
+                       memset(pos, '=', 4);
+                       pos += 4;
+                       break;
+               }
+               *pos++ = b32digits[((chunk.ptr[i+1] & 0x01) << 4) |
+                                                  (chunk.ptr[i+2] >> 4)];
+               if (i+3 >= chunk.len)
+               {
+                       *pos++ = b32digits[(chunk.ptr[i+2] & 0x0F) << 1];
+                       memset(pos, '=', 3);
+                       pos += 3;
+                       break;
+               }
+               *pos++ = b32digits[((chunk.ptr[i+2] & 0x0F) << 1) |
+                                                  (chunk.ptr[i+3] >> 7)];
+               *pos++ = b32digits[(chunk.ptr[i+3] & 0x7F) >> 2];
+               if (i+4 >= chunk.len)
+               {
+                       *pos++ = b32digits[(chunk.ptr[i+3] & 0x03) << 3];
+                       *pos++ = '=';
+                       break;
+               }
+               *pos++ = b32digits[((chunk.ptr[i+3] & 0x03) << 3) |
+                                                  (chunk.ptr[i+4] >> 5)];
+               *pos++ = b32digits[chunk.ptr[i+4] & 0x1F];
+       }
+       *pos = '\0';
+       return chunk_create(buf, len * 8 / 5);
+}
+
+/**
+ * Described in header.
+ */
+int chunk_compare(chunk_t a, chunk_t b)
+{
+       int compare_len = a.len - b.len;
+       int len = (compare_len < 0)? a.len : b.len;
+
+       if (compare_len != 0 || len == 0)
+       {
+               return compare_len;
+       }
+       return memcmp(a.ptr, b.ptr, len);
+};
+
+
+/**
+ * Described in header.
+ */
+bool chunk_increment(chunk_t chunk)
+{
+       int i;
+
+       for (i = chunk.len - 1; i >= 0; i--)
+       {
+               if (++chunk.ptr[i] != 0)
+               {
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+/**
+ * Remove non-printable characters from a chunk.
+ */
+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace)
+{
+       bool printable = TRUE;
+       int i;
+
+       if (sane)
+       {
+               *sane = chunk_clone(chunk);
+       }
+       for (i = 0; i < chunk.len; i++)
+       {
+               if (!isprint(chunk.ptr[i]))
+               {
+                       if (sane)
+                       {
+                               sane->ptr[i] = replace;
+                       }
+                       printable = FALSE;
+               }
+       }
+       return printable;
+}
+
+/**
+ * Described in header.
+ *
+ * The implementation is based on Paul Hsieh's SuperFastHash:
+ *      http://www.azillionmonkeys.com/qed/hash.html
+ */
+u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
+{
+       u_char *data = chunk.ptr;
+       size_t len = chunk.len;
+       u_int32_t tmp;
+       int rem;
+
+       if (!len || data == NULL)
+       {
+               return 0;
+       }
+
+       rem = len & 3;
+       len >>= 2;
+
+       /* Main loop */
+       for (; len > 0; --len)
+       {
+               hash += get16bits(data);
+               tmp   = (get16bits(data + 2) << 11) ^ hash;
+               hash  = (hash << 16) ^ tmp;
+               data += 2 * sizeof(u_int16_t);
+               hash += hash >> 11;
+       }
+
+       /* Handle end cases */
+       switch (rem)
+       {
+               case 3:
+               {
+                       hash += get16bits(data);
+                       hash ^= hash << 16;
+                       hash ^= data[sizeof(u_int16_t)] << 18;
+                       hash += hash >> 11;
+                       break;
+               }
+               case 2:
+               {
+                       hash += get16bits(data);
+                       hash ^= hash << 11;
+                       hash += hash >> 17;
+                       break;
+               }
+               case 1:
+               {
+                       hash += *data;
+                       hash ^= hash << 10;
+                       hash += hash >> 1;
+                       break;
+               }
+       }
+
+       /* Force "avalanching" of final 127 bits */
+       hash ^= hash << 3;
+       hash += hash >> 5;
+       hash ^= hash << 4;
+       hash += hash >> 17;
+       hash ^= hash << 25;
+       hash += hash >> 6;
+
+       return hash;
+}
+
+/**
+ * Described in header.
+ */
+u_int32_t chunk_hash(chunk_t chunk)
+{
+       return chunk_hash_inc(chunk, chunk.len);
+}
+
+/**
+ * Described in header.
+ */
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+                                         const void *const *args)
+{
+       chunk_t *chunk = *((chunk_t**)(args[0]));
+       bool first = TRUE;
+       chunk_t copy = *chunk;
+       int written = 0;
+
+       if (!spec->hash)
+       {
+               u_int chunk_len = chunk->len;
+               const void *new_args[] = {&chunk->ptr, &chunk_len};
+               return mem_printf_hook(data, spec, new_args);
+       }
+
+       while (copy.len > 0)
+       {
+               if (first)
+               {
+                       first = FALSE;
+               }
+               else
+               {
+                       written += print_in_hook(data, ":");
+               }
+               written += print_in_hook(data, "%02x", *copy.ptr++);
+               copy.len--;
+       }
+       return written;
+}
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
new file mode 100644 (file)
index 0000000..865c1b8
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chunk chunk
+ * @{ @ingroup utils
+ */
+
+#ifndef CHUNK_H_
+#define CHUNK_H_
+
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+typedef struct chunk_t chunk_t;
+
+/**
+ * General purpose pointer/length abstraction.
+ */
+struct chunk_t {
+       /** Pointer to start of data */
+       u_char *ptr;
+       /** Length of data in bytes */
+       size_t len;
+};
+
+#include "../utils.h"
+
+/**
+ * A { NULL, 0 }-chunk handy for initialization.
+ */
+extern chunk_t chunk_empty;
+
+/**
+ * Create a new chunk pointing to "ptr" with length "len"
+ */
+static inline chunk_t chunk_create(u_char *ptr, size_t len)
+{
+       chunk_t chunk = {ptr, len};
+       return chunk;
+}
+
+/**
+ * Create a clone of a chunk pointing to "ptr"
+ */
+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
+
+/**
+ * Calculate length of multiple chunks
+ */
+size_t chunk_length(const char *mode, ...);
+
+/**
+ * Concatenate chunks into a chunk pointing to "ptr".
+ *
+ * The mode string specifies the number of chunks, and how to handle each of
+ * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
+ * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
+ */
+chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
+
+/**
+ * Split up a chunk into parts, "mode" is a string of "a" (alloc),
+ * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
+ * it should get allocated on heap, copied into existing chunk, or the chunk
+ * should point into "chunk". The length of each part is an argument before
+ * each target chunk. E.g.:
+ * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
+ */
+void chunk_split(chunk_t chunk, const char *mode, ...);
+
+/**
+ * Write the binary contents of a chunk_t to a file
+ *
+ * @param chunk                        contents to write to file
+ * @param path                 path where file is written to
+ * @param label                        label specifying file type
+ * @param mask                 file mode creation mask
+ * @param force                        overwrite existing file by force
+ * @return                             TRUE if write operation was successful
+ */
+bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force);
+
+/**
+ * Convert a chunk of data to hex encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
+ *
+ * @param chunk                        data to convert to hex encoding
+ * @param buf                  buffer to write to, NULL to malloc
+ * @param uppercase            TRUE to use uppercase letters
+ * @return                             chunk of encoded data
+ */
+chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
+
+/**
+ * Convert a hex encoded in a binary chunk.
+ *
+ * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
+ * bytes. It is filled by the right to give correct values for short inputs.
+ *
+ * @param hex                  hex encoded input data
+ * @param buf                  buffer to write decoded data, NULL to malloc
+ * @return                             converted data
+ */
+chunk_t chunk_from_hex(chunk_t hex, char *buf);
+
+/**
+ * Convert a chunk of data to its base64 encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
+ *
+ * @param chunk                        data to convert
+ * @param buf                  buffer to write to, NULL to malloc
+ * @return                             chunk of encoded data
+ */
+chunk_t chunk_to_base64(chunk_t chunk, char *buf);
+
+/**
+ * Convert a base64 in a binary chunk.
+ *
+ * If buf is supplied, it must hold at least (base64.len / 4 * 3).
+ *
+ * @param base64               base64 encoded input data
+ * @param buf                  buffer to write decoded data, NULL to malloc
+ * @return                             converted data
+ */
+chunk_t chunk_from_base64(chunk_t base64, char *buf);
+
+/**
+ * Convert a chunk of data to its base32 encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
+ *
+ * @param chunk                        data to convert
+ * @param buf                  buffer to write to, NULL to malloc
+ * @return                             chunk of encoded data
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf);
+
+/**
+ * Free contents of a chunk
+ */
+static inline void chunk_free(chunk_t *chunk)
+{
+       free(chunk->ptr);
+       *chunk = chunk_empty;
+}
+
+/**
+ * Overwrite the contents of a chunk and free it
+ */
+static inline void chunk_clear(chunk_t *chunk)
+{
+       if (chunk->ptr)
+       {
+               memwipe(chunk->ptr, chunk->len);
+               chunk_free(chunk);
+       }
+}
+
+/**
+ * Initialize a chunk using a char array
+ */
+#define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})})
+
+/**
+ * Initialize a chunk to point to a thing
+ */
+#define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing))
+
+/**
+ * Allocate a chunk on the heap
+ */
+#define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
+
+/**
+ * Allocate a chunk on the stack
+ */
+#define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
+
+/**
+ * Clone a chunk on heap
+ */
+#define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
+
+/**
+ * Clone a chunk on stack
+ */
+#define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
+
+/**
+ * Concatenate chunks into a chunk on heap
+ */
+#define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
+
+/**
+ * Concatenate chunks into a chunk on stack
+ */
+#define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
+
+/**
+ * Skip n bytes in chunk (forward pointer, shorten length)
+ */
+static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
+{
+       if (chunk.len > bytes)
+       {
+               chunk.ptr += bytes;
+               chunk.len -= bytes;
+               return chunk;
+       }
+       return chunk_empty;
+}
+
+/**
+ * Skip a leading zero-valued byte
+ */
+static inline chunk_t chunk_skip_zero(chunk_t chunk)
+{
+       if (chunk.len > 1 && *chunk.ptr == 0x00)
+       {
+               chunk.ptr++;
+               chunk.len--;
+       }
+       return chunk;
+}
+
+
+/**
+ *  Compare two chunks, returns zero if a equals b
+ *  or negative/positive if a is small/greater than b
+ */
+int chunk_compare(chunk_t a, chunk_t b);
+
+/**
+ * Compare two chunks for equality,
+ * NULL chunks are never equal.
+ */
+static inline bool chunk_equals(chunk_t a, chunk_t b)
+{
+       return a.ptr != NULL  && b.ptr != NULL &&
+                       a.len == b.len && memeq(a.ptr, b.ptr, a.len);
+}
+
+/**
+ * Compare two chunks (given as pointers) for equality (useful as callback),
+ * NULL chunks are never equal.
+ */
+static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
+{
+       return a != NULL && b != NULL && chunk_equals(*a, *b);
+}
+
+/**
+ * Increment a chunk, as it would reprensent a network order integer.
+ *
+ * @param chunk                        chunk to increment
+ * @return                             TRUE if an overflow occurred
+ */
+bool chunk_increment(chunk_t chunk);
+
+/**
+ * Check if a chunk has printable characters only.
+ *
+ * If sane is given, chunk is cloned into sane and all non printable characters
+ * get replaced by "replace".
+ *
+ * @param chunk                        chunk to check for printability
+ * @param sane                 pointer where sane version is allocated, or NULL
+ * @param replace              character to use for replaceing unprintable characters
+ * @return                             TRUE if all characters in chunk are printable
+ */
+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
+
+/**
+ * Computes a 32 bit hash of the given chunk.
+ * Note: This hash is only intended for hash tables not for cryptographic purposes.
+ */
+u_int32_t chunk_hash(chunk_t chunk);
+
+/**
+ * Incremental version of chunk_hash. Use this to hash two or more chunks.
+ */
+u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
+
+/**
+ * printf hook function for chunk_t.
+ *
+ * Arguments are:
+ *     chunk_t *chunk
+ * Use #-modifier to print a compact version
+ */
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+                                         const void *const *args);
+
+#endif /** CHUNK_H_ @}*/
index 8b2173a..cdf2291 100644 (file)
@@ -29,7 +29,7 @@ typedef struct identification_t identification_t;
 typedef enum id_match_t id_match_t;
 typedef enum id_part_t id_part_t;
 
-#include <chunk.h>
+#include <utils/chunk.h>
 #include <collections/enumerator.h>
 
 /**