From 125b37af6d39e445086b6e80f60b3316a7602b6c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 16 Oct 2012 15:53:49 +0200 Subject: Moved chunk_t to utils folder --- src/libhydra/attributes/attribute_handler.h | 2 +- src/libstrongswan/Android.mk | 4 +- src/libstrongswan/Makefile.am | 8 +- src/libstrongswan/chunk.c | 690 --------------------- src/libstrongswan/chunk.h | 318 ---------- src/libstrongswan/fetcher/fetcher.h | 2 +- src/libstrongswan/library.h | 2 +- src/libstrongswan/networking/host.h | 2 +- .../plugins/agent/agent_private_key.c | 2 +- src/libstrongswan/plugins/mysql/mysql_database.c | 2 +- src/libstrongswan/plugins/pkcs11/pkcs11_library.h | 2 +- src/libstrongswan/utils/chunk.c | 690 +++++++++++++++++++++ src/libstrongswan/utils/chunk.h | 318 ++++++++++ src/libstrongswan/utils/identification.h | 2 +- 14 files changed, 1022 insertions(+), 1022 deletions(-) delete mode 100644 src/libstrongswan/chunk.c delete mode 100644 src/libstrongswan/chunk.h create mode 100644 src/libstrongswan/utils/chunk.c create mode 100644 src/libstrongswan/utils/chunk.h (limited to 'src') diff --git a/src/libhydra/attributes/attribute_handler.h b/src/libhydra/attributes/attribute_handler.h index 91fa4e5b0..bc488f6cb 100644 --- a/src/libhydra/attributes/attribute_handler.h +++ b/src/libhydra/attributes/attribute_handler.h @@ -21,7 +21,7 @@ #ifndef ATTRIBUTE_HANDLER_H_ #define ATTRIBUTE_HANDLER_H_ -#include +#include #include #include diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index ef9f378c6..7308e3fee 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -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 diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 77120c6e5..07d04b03e 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -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 index d7f1c31d9..000000000 --- a/src/libstrongswan/chunk.c +++ /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 . - * - * 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 -#include -#include -#include -#include - -#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 index 91b23da3b..000000000 --- a/src/libstrongswan/chunk.h +++ /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 . - * - * 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 -#include -#include -#ifdef HAVE_ALLOCA_H -#include -#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_ @}*/ diff --git a/src/libstrongswan/fetcher/fetcher.h b/src/libstrongswan/fetcher/fetcher.h index 5b734da3d..58451aef2 100644 --- a/src/libstrongswan/fetcher/fetcher.h +++ b/src/libstrongswan/fetcher/fetcher.h @@ -26,7 +26,7 @@ typedef struct fetcher_t fetcher_t; typedef enum fetcher_option_t fetcher_option_t; #include -#include +#include /** * Constructor function which creates fetcher instances. diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h index c8e882743..699d5cb2e 100644 --- a/src/libstrongswan/library.h +++ b/src/libstrongswan/library.h @@ -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" diff --git a/src/libstrongswan/networking/host.h b/src/libstrongswan/networking/host.h index cae2a4ff0..1c49b1a50 100644 --- a/src/libstrongswan/networking/host.h +++ b/src/libstrongswan/networking/host.h @@ -34,7 +34,7 @@ typedef struct host_t host_t; #include #include -#include +#include /** * Differences between two hosts. They differ in diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index 60b57ad2d..8d49431b3 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #ifndef UNIX_PATH_MAX diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c index 12a8ff54f..d31e1eb33 100644 --- a/src/libstrongswan/plugins/mysql/mysql_database.c +++ b/src/libstrongswan/plugins/mysql/mysql_database.c @@ -20,7 +20,7 @@ #include "mysql_database.h" #include -#include +#include #include #include #include diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h index 81414a25f..f225b9b8d 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h @@ -30,7 +30,7 @@ typedef struct pkcs11_library_t pkcs11_library_t; #include "pkcs11.h" #include -#include +#include #include /** diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c new file mode 100644 index 000000000..d7f1c31d9 --- /dev/null +++ b/src/libstrongswan/utils/chunk.c @@ -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 . + * + * 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 +#include +#include +#include +#include + +#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 index 000000000..865c1b82f --- /dev/null +++ b/src/libstrongswan/utils/chunk.h @@ -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 . + * + * 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 +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#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_ @}*/ diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index 8b2173afb..cdf229127 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -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 +#include #include /** -- cgit v1.2.3