From 595b6d9a828538072dcf65c276b848a02698fdfe Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 11:29:46 +0100 Subject: [PATCH 01/11] chunk: Add functions to map file contents to a chunk --- src/libstrongswan/tests/suites/test_chunk.c | 44 +++++++++++- src/libstrongswan/utils/chunk.c | 80 +++++++++++++++++++++ src/libstrongswan/utils/chunk.h | 26 +++++++ 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c index 1c0bac10e..7971f5ca8 100644 --- a/src/libstrongswan/tests/suites/test_chunk.c +++ b/src/libstrongswan/tests/suites/test_chunk.c @@ -14,9 +14,10 @@ * for more details. */ - #include "test_suite.h" +#include + #include /******************************************************************************* @@ -774,6 +775,43 @@ START_TEST(test_chunk_hash_static) } END_TEST +/******************************************************************************* + * test for chunk_map and friends + */ + +START_TEST(test_chunk_map) +{ + chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); + char *path = "/tmp/strongswan-chunk-map-test"; + + ck_assert(chunk_write(contents, path, "chunk_map", 022, TRUE)); + + /* read */ + map = chunk_map(path, FALSE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + /* altering mapped chunk should not hurt */ + *map = chunk_empty; + ck_assert(chunk_unmap(map)); + + /* write */ + map = chunk_map(path, TRUE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + map->ptr[0] = 0x06; + ck_assert(chunk_unmap(map)); + + /* verify write */ + contents.ptr[0] = 0x06; + map = chunk_map(path, FALSE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + ck_assert(chunk_unmap(map)); + + unlink(path); +} +END_TEST + /******************************************************************************* * printf_hook tests */ @@ -891,6 +929,10 @@ Suite *chunk_suite_create() tcase_add_test(tc, test_chunk_hash_static); suite_add_tcase(s, tc); + tc = tcase_create("chunk_map"); + tcase_add_test(tc, test_chunk_map); + suite_add_tcase(s, tc); + tc = tcase_create("printf_hook"); tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data)); tcase_add_loop_test(tc, test_printf_hook_plus, 0, countof(printf_hook_data)); diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 644b8060f..5c00c5b32 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -275,6 +276,85 @@ chunk_t chunk_from_fd(int fd) return chunk_clone(chunk_create(buf, total)); } +/** + * Implementation for mmap()ed chunks + */ +typedef struct { + /* public chunk interface */ + chunk_t public; + /* FD of open file */ + int fd; + /* mmap() address */ + void *map; + /* size of map */ + size_t len; +} mmaped_chunk_t; + +/** + * See header. + */ +chunk_t *chunk_map(char *path, bool wr) +{ + mmaped_chunk_t *chunk; + struct stat sb; + int tmp; + + INIT(chunk, + .fd = open(path, wr ? O_RDWR : O_RDONLY), + ); + + if (chunk->fd == -1) + { + free(chunk); + return NULL; + } + if (fstat(chunk->fd, &sb) == -1) + { + tmp = errno; + chunk_unmap(&chunk->public); + errno = tmp; + return NULL; + } + chunk->len = sb.st_size; + /* map non-empty files only, as mmap() complains otherwise */ + if (chunk->len) + { + /* in read-only mode, we allow writes, but don't sync to disk */ + chunk->map = mmap(NULL, chunk->len, PROT_READ | PROT_WRITE, + wr ? MAP_SHARED : MAP_PRIVATE, chunk->fd, 0); + if (chunk->map == MAP_FAILED) + { + tmp = errno; + chunk_unmap(&chunk->public); + errno = tmp; + return NULL; + } + } + chunk->public = chunk_create(chunk->map, chunk->len); + return &chunk->public; +} + +/** + * See header. + */ +bool chunk_unmap(chunk_t *public) +{ + mmaped_chunk_t *chunk; + bool ret = FALSE; + int tmp = 0; + + chunk = (mmaped_chunk_t*)public; + if (chunk->map && chunk->map != MAP_FAILED) + { + ret = munmap(chunk->map, chunk->len) == 0; + tmp = errno; + } + close(chunk->fd); + free(chunk); + errno = tmp; + + return ret; +} /** hex conversion digits */ static char hexdig_upper[] = "0123456789ABCDEF"; diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 80b6237ec..92a96ffba 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -107,6 +107,32 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force */ chunk_t chunk_from_fd(int fd); +/** + * mmap() a file to a chunk + * + * The returned chunk structure is allocated from heap, but it must be freed + * through chunk_unmap(). A user may alter the chunk ptr or len, but must pass + * the chunk pointer returned from chunk_map() to chunk_unmap() after use. + * + * On error, errno is set appropriately. + * + * @param path path of file to map + * @param wr TRUE to sync writes to disk + * @return mapped chunk, NULL on error + */ +chunk_t *chunk_map(char *path, bool wr); + +/** + * munmap() a chunk previously mapped with chunk_map() + * + * When unmapping a writeable map, the return value should be checked to + * ensure changes landed on disk. + * + * @param chunk pointer returned from chunk_map() + * @return TRUE of changes written back to file + */ +bool chunk_unmap(chunk_t *chunk); + /** * Convert a chunk of data to hex encoding. * From 1c4a3459f72da4391c1befe22e62356d838af46d Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 12:19:20 +0100 Subject: [PATCH 02/11] chunk: Use dynamically allocated buffer in chunk_from_fd() When acting on files, we can use fstat() to estimate the buffer size. On non-file FDs, we dynamically increase an allocated buffer. Additionally we slightly change the function signature to properly handle zero-length files and add appropriate unit tests. --- src/libstrongswan/tests/suites/test_chunk.c | 84 +++++++++++++++++++++ src/libstrongswan/utils/chunk.c | 53 ++++++++++--- src/libstrongswan/utils/chunk.h | 7 +- src/pki/commands/issue.c | 16 +++- src/pki/commands/keyid.c | 9 ++- src/pki/commands/print.c | 7 +- src/pki/commands/pub.c | 9 ++- src/pki/commands/req.c | 7 +- src/pki/commands/self.c | 8 +- src/pki/commands/verify.c | 8 +- 10 files changed, 183 insertions(+), 25 deletions(-) diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c index 7971f5ca8..3492a7f7b 100644 --- a/src/libstrongswan/tests/suites/test_chunk.c +++ b/src/libstrongswan/tests/suites/test_chunk.c @@ -17,8 +17,13 @@ #include "test_suite.h" #include +#include +#include +#include +#include #include +#include /******************************************************************************* * utilities @@ -812,6 +817,79 @@ START_TEST(test_chunk_map) } END_TEST +/******************************************************************************* + * test for chunk_from_fd + */ + +START_TEST(test_chunk_from_fd_file) +{ + chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); + char *path = "/tmp/strongswan-chunk-fd-test"; + int fd; + + ck_assert(chunk_write(contents, path, "chunk_fd", 022, TRUE)); + + fd = open(path, O_RDONLY); + ck_assert(fd != -1); + + ck_assert(chunk_from_fd(fd, &in)); + close(fd); + ck_assert_msg(chunk_equals(in, contents), "%B", &in); + unlink(path); + free(in.ptr); +} +END_TEST + +START_TEST(test_chunk_from_fd_skt) +{ + chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); + int s[2]; + + ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0); + ck_assert(write(s[1], contents.ptr, contents.len) == contents.len); + close(s[1]); + ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno)); + close(s[0]); + ck_assert_msg(chunk_equals(in, contents), "%B", &in); + free(in.ptr); +} +END_TEST + +#define FROM_FD_COUNT 8192 + +void *chunk_from_fd_run(void *data) +{ + int i, fd = (uintptr_t)data; + + for (i = 0; i < FROM_FD_COUNT; i++) + { + ck_assert(write(fd, &i, sizeof(i)) == sizeof(i)); + } + close(fd); + return NULL; +} + +START_TEST(test_chunk_from_fd_huge) +{ + thread_t *thread; + chunk_t in; + int s[2], i; + + ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0); + + thread = thread_create(chunk_from_fd_run, (void*)(uintptr_t)s[1]); + ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno)); + ck_assert_int_eq(in.len, FROM_FD_COUNT * sizeof(i)); + for (i = 0; i < FROM_FD_COUNT; i++) + { + ck_assert_int_eq(((int*)in.ptr)[i], i); + } + thread->join(thread); + close(s[0]); + free(in.ptr); +} +END_TEST + /******************************************************************************* * printf_hook tests */ @@ -933,6 +1011,12 @@ Suite *chunk_suite_create() tcase_add_test(tc, test_chunk_map); suite_add_tcase(s, tc); + tc = tcase_create("chunk_from_fd"); + tcase_add_test(tc, test_chunk_from_fd_file); + tcase_add_test(tc, test_chunk_from_fd_skt); + tcase_add_test(tc, test_chunk_from_fd_huge); + suite_add_tcase(s, tc); + tc = tcase_create("printf_hook"); tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data)); tcase_add_loop_test(tc, test_printf_hook_plus, 0, countof(printf_hook_data)); diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 5c00c5b32..e308418df 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -247,33 +247,62 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force /** * Described in header. */ -chunk_t chunk_from_fd(int fd) +bool chunk_from_fd(int fd, chunk_t *out) { - char buf[8096]; - char *pos = buf; - ssize_t len, total = 0; + struct stat sb; + char *buf, *tmp; + ssize_t len, total = 0, bufsize; + + if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode)) + { + bufsize = sb.st_size; + } + else + { + bufsize = 256; + } + buf = malloc(bufsize); + if (!buf) + { /* for huge files */ + return FALSE; + } while (TRUE) { - len = read(fd, pos, buf + sizeof(buf) - pos); + len = read(fd, buf + total, bufsize - total); if (len < 0) { - DBG1(DBG_LIB, "reading from file descriptor failed: %s", - strerror(errno)); - return chunk_empty; + free(buf); + return FALSE; } if (len == 0) { break; } total += len; - if (total == sizeof(buf)) + if (total == bufsize) { - DBG1(DBG_LIB, "buffer too small to read from file descriptor"); - return chunk_empty; + bufsize *= 2; + tmp = realloc(buf, bufsize); + if (!tmp) + { + free(buf); + return FALSE; + } + buf = tmp; } } - return chunk_clone(chunk_create(buf, total)); + if (total == 0) + { + free(buf); + buf = NULL; + } + else if (total < bufsize) + { + buf = realloc(buf, total); + } + *out = chunk_create(buf, total); + return TRUE; } /** diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 92a96ffba..1228da30e 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -102,10 +102,13 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force /** * Store data read from FD into a chunk * + * On error, errno is set appropriately. + * * @param fd file descriptor to read from - * @return chunk or chunk_empty on failure + * @param chunk chunk receiving allocated buffer + * @return TRUE if successful, FALSE on failure */ -chunk_t chunk_from_fd(int fd); +bool chunk_from_fd(int fd, chunk_t *chunk); /** * mmap() a file to a chunk diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index 000f63d1a..d5c33b89f 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -14,6 +14,7 @@ */ #include +#include #include "pki.h" @@ -382,7 +383,12 @@ static int issue() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "%s: ", strerror(errno)); + error = "reading certificate request failed"; + goto end; + } cert_req = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PKCS10_REQUEST, BUILD_BLOB, chunk, BUILD_END); @@ -425,7 +431,12 @@ static int issue() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "%s: ", strerror(errno)); + error = "reading public key failed"; + goto end; + } public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); @@ -562,4 +573,3 @@ static void __attribute__ ((constructor))reg() } }); } - diff --git a/src/pki/commands/keyid.c b/src/pki/commands/keyid.c index 353670e32..64bb3cc2c 100644 --- a/src/pki/commands/keyid.c +++ b/src/pki/commands/keyid.c @@ -13,6 +13,8 @@ * for more details. */ +#include + #include "pki.h" #include @@ -89,7 +91,11 @@ static int keyid() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "reading input failed: %s\n", strerror(errno)); + return 1; + } cred = lib->creds->create(lib->creds, type, subtype, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); @@ -165,4 +171,3 @@ static void __attribute__ ((constructor))reg() } }); } - diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c index 2261e44ff..077c1ef3e 100644 --- a/src/pki/commands/print.c +++ b/src/pki/commands/print.c @@ -22,6 +22,7 @@ #include #include +#include /** * Print public key information @@ -510,7 +511,11 @@ static int print() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "reading input failed: %s\n", strerror(errno)); + return 1; + } cred = lib->creds->create(lib->creds, type, subtype, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c index 7f88055ef..260044c4e 100644 --- a/src/pki/commands/pub.c +++ b/src/pki/commands/pub.c @@ -13,6 +13,8 @@ * for more details. */ +#include + #include "pki.h" #include @@ -108,7 +110,11 @@ static int pub() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "reading input failed: %s\n", strerror(errno)); + return 1; + } cred = lib->creds->create(lib->creds, type, subtype, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); @@ -186,4 +192,3 @@ static void __attribute__ ((constructor))reg() } }); } - diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c index 628463e7b..64609597d 100644 --- a/src/pki/commands/req.c +++ b/src/pki/commands/req.c @@ -16,6 +16,7 @@ */ #include +#include #include "pki.h" @@ -118,7 +119,11 @@ static int req() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "reading private key failed: %s\n", strerror(errno)); + return 1; + } private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index 6bf0b1353..c28c9c291 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -14,6 +14,7 @@ */ #include +#include #include "pki.h" @@ -273,7 +274,12 @@ static int self() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "%s: ", strerror(errno)); + error = "reading private key failed"; + goto end; + } private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); diff --git a/src/pki/commands/verify.c b/src/pki/commands/verify.c index 96b2b5065..f30dda94d 100644 --- a/src/pki/commands/verify.c +++ b/src/pki/commands/verify.c @@ -13,6 +13,8 @@ * for more details. */ +#include + #include "pki.h" #include @@ -57,7 +59,11 @@ static int verify() { chunk_t chunk; - chunk = chunk_from_fd(0); + if (!chunk_from_fd(0, &chunk)) + { + fprintf(stderr, "reading certificate failed: %s\n", strerror(errno)); + return 1; + } cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); From 37374a292aea466063bf7777929122299d493326 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:07:12 +0100 Subject: [PATCH 03/11] chunk: Provide a fallback chunk_map() if mmap is not available --- configure.ac | 2 +- src/libstrongswan/utils/chunk.c | 47 ++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index ab90571f7..10f1e1929 100644 --- a/configure.ac +++ b/configure.ac @@ -495,7 +495,7 @@ AC_CHECK_FUNC( ) AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r) -AC_CHECK_FUNCS(fmemopen funopen) +AC_CHECK_FUNCS(fmemopen funopen mmap) AC_CHECK_HEADERS(sys/sockio.h glob.h net/if_tun.h linux/fib_rules.h) AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h) diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index e308418df..5961407dd 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -18,7 +18,9 @@ #include #include #include -#include +#ifdef HAVE_MMAP +# include +#endif #include #include #include @@ -317,6 +319,8 @@ typedef struct { void *map; /* size of map */ size_t len; + /* do we write? */ + bool wr; } mmaped_chunk_t; /** @@ -330,6 +334,7 @@ chunk_t *chunk_map(char *path, bool wr) INIT(chunk, .fd = open(path, wr ? O_RDWR : O_RDONLY), + .wr = wr, ); if (chunk->fd == -1) @@ -344,6 +349,7 @@ chunk_t *chunk_map(char *path, bool wr) errno = tmp; return NULL; } +#ifdef HAVE_MMAP chunk->len = sb.st_size; /* map non-empty files only, as mmap() complains otherwise */ if (chunk->len) @@ -360,6 +366,17 @@ chunk_t *chunk_map(char *path, bool wr) } } chunk->public = chunk_create(chunk->map, chunk->len); +#else /* !HAVE_MMAP */ + if (!chunk_from_fd(chunk->fd, &chunk->public)) + { + tmp = errno; + chunk_unmap(&chunk->public); + errno = tmp; + return NULL; + } + chunk->map = chunk->public.ptr; + chunk->len = chunk->public.len; +#endif /* !HAVE_MMAP */ return &chunk->public; } @@ -373,11 +390,39 @@ bool chunk_unmap(chunk_t *public) int tmp = 0; chunk = (mmaped_chunk_t*)public; +#ifdef HAVE_MMAP if (chunk->map && chunk->map != MAP_FAILED) { ret = munmap(chunk->map, chunk->len) == 0; tmp = errno; } +#else /* !HAVE_MMAP */ + if (chunk->wr) + { + if (lseek(chunk->fd, 0, SEEK_SET) != -1) + { + int len, total = 0; + + ret = TRUE; + while (total < chunk->len) + { + len = write(chunk->fd, chunk->map + total, chunk->len - total); + if (len <= 0) + { + ret = FALSE; + break; + } + total += len; + } + } + tmp = errno; + } + else + { + ret = TRUE; + } + free(chunk->map); +#endif /* !HAVE_MMAP */ close(chunk->fd); free(chunk); errno = tmp; From b9ee059ca99bc8fb2a8854b35fef5a7672a03e1b Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:22:01 +0100 Subject: [PATCH 04/11] chunk: Externalize error reporting in chunk_write() This avoids passing that arbitrary label just for error messages, and gives greater flexibility in handling errors. --- src/libcharon/plugins/stroke/stroke_cred.c | 11 +++++- src/libstrongswan/tests/suites/test_chunk.c | 4 +-- src/libstrongswan/utils/chunk.c | 15 ++++----- src/libstrongswan/utils/chunk.h | 5 +-- src/openac/openac.c | 10 +++++- src/scepclient/scepclient.c | 37 ++++++++++++--------- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 8d0001271..224dd9803 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -521,7 +521,16 @@ METHOD(stroke_cred_t, cache_cert, void, if (cert->get_encoding(cert, CERT_ASN1_DER, &chunk)) { - chunk_write(chunk, buf, "crl", 022, TRUE); + if (chunk_write(chunk, buf, 022, TRUE)) + { + DBG1(DBG_CFG, " written crl file '%s' (%d bytes)", + buf, chunk.len); + } + else + { + DBG1(DBG_CFG, " writing crl file '%s' failed: %s", + buf, strerror(errno)); + } free(chunk.ptr); } } diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c index 3492a7f7b..e373fbdb6 100644 --- a/src/libstrongswan/tests/suites/test_chunk.c +++ b/src/libstrongswan/tests/suites/test_chunk.c @@ -789,7 +789,7 @@ START_TEST(test_chunk_map) chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); char *path = "/tmp/strongswan-chunk-map-test"; - ck_assert(chunk_write(contents, path, "chunk_map", 022, TRUE)); + ck_assert(chunk_write(contents, path, 022, TRUE)); /* read */ map = chunk_map(path, FALSE); @@ -827,7 +827,7 @@ START_TEST(test_chunk_from_fd_file) char *path = "/tmp/strongswan-chunk-fd-test"; int fd; - ck_assert(chunk_write(contents, path, "chunk_fd", 022, TRUE)); + ck_assert(chunk_write(contents, path, 022, TRUE)); fd = open(path, O_RDONLY); ck_assert(fd != -1); diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 5961407dd..47181719a 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -28,7 +28,6 @@ #include #include "chunk.h" -#include "debug.h" /** * Empty chunk. @@ -209,15 +208,16 @@ void chunk_split(chunk_t chunk, const char *mode, ...) /** * Described in header. */ -bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force) +bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force) { mode_t oldmask; FILE *fd; bool good = FALSE; + int tmp = 0; if (!force && access(path, F_OK) == 0) { - DBG1(DBG_LIB, " %s file '%s' already exists", label, path); + errno = EEXIST; return FALSE; } oldmask = umask(mask); @@ -226,23 +226,20 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force { 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)); + tmp = errno; } fclose(fd); } else { - DBG1(DBG_LIB, " could not open %s file '%s': %s", label, path, - strerror(errno)); + tmp = errno; } umask(oldmask); + errno = tmp; return good; } diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 1228da30e..33f66caec 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -90,14 +90,15 @@ void chunk_split(chunk_t chunk, const char *mode, ...); /** * Write the binary contents of a chunk_t to a file * + * If the write fails, errno is set appropriately. + * * @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); +bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force); /** * Store data read from FD into a chunk diff --git a/src/openac/openac.c b/src/openac/openac.c index 7074d44be..1996025e2 100644 --- a/src/openac/openac.c +++ b/src/openac/openac.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -515,11 +516,18 @@ int main(int argc, char **argv) /* write the attribute certificate to file */ if (attr_cert->get_encoding(attr_cert, CERT_ASN1_DER, &attr_chunk)) { - if (chunk_write(attr_chunk, outfile, "attribute cert", 0022, TRUE)) + if (chunk_write(attr_chunk, outfile, 0022, TRUE)) { + DBG1(DBG_APP, " written attribute cert file '%s' (%d bytes)", + outfile, attr_chunk.len); write_serial(serial); status = 0; } + else + { + DBG1(DBG_APP, " writing attribute cert file '%s' failed: %s", + outfile, strerror(errno)); + } } } else diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 1267370ba..ec892cc0b 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -975,9 +976,10 @@ int main(int argc, char **argv) { /* no PKCS#7 encoded CA+RA certificates, assume simple CA cert */ DBG1(DBG_APP, "unable to parse PKCS#7, assuming plain CA cert"); - if (!chunk_write(scep_response, ca_path, "ca cert", 0022, force)) + if (!chunk_write(scep_response, ca_path, 0022, force)) { - exit_scepclient("could not write ca cert file '%s'", ca_path); + exit_scepclient("could not write ca cert file '%s': %s", + ca_path, strerror(errno)); } } else @@ -1031,10 +1033,10 @@ int main(int argc, char **argv) } if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding) || - !chunk_write(encoding, path, - ca_cert ? "ca cert" : "ra cert", 0022, force)) + !chunk_write(encoding, path, 0022, force)) { - exit_scepclient("could not write cert file '%s'", path); + exit_scepclient("could not write cert file '%s': %s", + path, strerror(errno)); } chunk_free(&encoding); } @@ -1149,9 +1151,10 @@ int main(int argc, char **argv) join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs10); - if (!chunk_write(pkcs10_encoding, path, "pkcs10", 0022, force)) + if (!chunk_write(pkcs10_encoding, path, 0022, force)) { - exit_scepclient("could not write pkcs10 file '%s'", path); + exit_scepclient("could not write pkcs10 file '%s': %s", + path, strerror(errno)); } filetype_out &= ~PKCS10; /* delete PKCS10 flag */ } @@ -1172,9 +1175,10 @@ int main(int argc, char **argv) DBG2(DBG_APP, "building pkcs1 object:"); if (!private_key->get_encoding(private_key, PRIVKEY_ASN1_DER, &pkcs1) || - !chunk_write(pkcs1, path, "pkcs1", 0066, force)) + !chunk_write(pkcs1, path, 0066, force)) { - exit_scepclient("could not write pkcs1 file '%s'", path); + exit_scepclient("could not write pkcs1 file '%s': %s", + path, strerror(errno)); } filetype_out &= ~PKCS1; /* delete PKCS1 flag */ } @@ -1236,9 +1240,10 @@ int main(int argc, char **argv) { exit_scepclient("encoding certificate failed"); } - if (!chunk_write(encoding, path, "self-signed cert", 0022, force)) + if (!chunk_write(encoding, path, 0022, force)) { - exit_scepclient("could not write self-signed cert file '%s'", path); + exit_scepclient("could not write self-signed cert file '%s': %s", + path, strerror(errno)); } chunk_free(&encoding); filetype_out &= ~CERT_SELF; /* delete CERT_SELF flag */ @@ -1300,9 +1305,10 @@ int main(int argc, char **argv) join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs7); - if (!chunk_write(pkcs7, path, "pkcs7 encrypted request", 0022, force)) + if (!chunk_write(pkcs7, path, 0022, force)) { - exit_scepclient("could not write pkcs7 file '%s'", path); + exit_scepclient("could not write pkcs7 file '%s': %s", + path, strerror(errno)); } filetype_out &= ~PKCS7; /* delete PKCS7 flag */ } @@ -1460,9 +1466,10 @@ int main(int argc, char **argv) exit_scepclient("multiple certs received, only first stored"); } if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding) || - !chunk_write(encoding, path, "requested cert", 0022, force)) + !chunk_write(encoding, path, 0022, force)) { - exit_scepclient("could not write cert file '%s'", path); + exit_scepclient("could not write cert file '%s': %s", + path, strerror(errno)); } chunk_free(&encoding); stored = TRUE; From 69be6a9e052d100b993519487ca174fad1401afb Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:50:30 +0100 Subject: [PATCH 05/11] integrity-checker: Use chunk_map() instead of non-portable mmap() --- src/libstrongswan/utils/integrity_checker.c | 37 ++++----------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/src/libstrongswan/utils/integrity_checker.c b/src/libstrongswan/utils/integrity_checker.c index d59a76232..b66df02e7 100644 --- a/src/libstrongswan/utils/integrity_checker.c +++ b/src/libstrongswan/utils/integrity_checker.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -61,40 +60,17 @@ METHOD(integrity_checker_t, build_file, u_int32_t, private_integrity_checker_t *this, char *file, size_t *len) { u_int32_t checksum; - chunk_t contents; - struct stat sb; - void *addr; - int fd; + chunk_t *contents; - fd = open(file, O_RDONLY); - if (fd == -1) + contents = chunk_map(file, FALSE); + if (!contents) { DBG1(DBG_LIB, " opening '%s' failed: %s", file, strerror(errno)); return 0; } - - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, " getting file size of '%s' failed: %s", file, - strerror(errno)); - close(fd); - return 0; - } - - addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, " mapping '%s' failed: %s", file, strerror(errno)); - close(fd); - return 0; - } - - *len = sb.st_size; - contents = chunk_create(addr, sb.st_size); - checksum = chunk_hash_static(contents); - - munmap(addr, sb.st_size); - close(fd); + *len = contents->len; + checksum = chunk_hash_static(*contents); + chunk_unmap(contents); return checksum; } @@ -318,4 +294,3 @@ integrity_checker_t *integrity_checker_create(char *checksum_library) } return &this->public; } - From 39badc53cd217abcbc5d4275cd962d2253afe484 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:48:23 +0100 Subject: [PATCH 06/11] libfast: Use chunk_map() instead of non-portable mmap() --- src/libfast/fast_request.c | 39 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/libfast/fast_request.c b/src/libfast/fast_request.c index 0673750b7..a56a59167 100644 --- a/src/libfast/fast_request.c +++ b/src/libfast/fast_request.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -294,31 +293,17 @@ METHOD(fast_request_t, serve, void, METHOD(fast_request_t, sendfile, bool, private_fast_request_t *this, char *path, char *mime) { - struct stat sb; - chunk_t data; - void *addr; - int fd, written; + chunk_t *data; + int written; char buf[24]; - fd = open(path, O_RDONLY); - if (fd == -1) + data = chunk_map(path, FALSE); + if (!data) { return FALSE; } - if (fstat(fd, &sb) == -1) - { - close(fd); - return FALSE; - } - addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - close(fd); - return FALSE; - } - /* FCGX does not like large integers, print to a buffer using libc */ - snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size); + snprintf(buf, sizeof(buf), "%lld", (int64_t)data->len); FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf); if (mime) { @@ -326,22 +311,18 @@ METHOD(fast_request_t, sendfile, bool, } FCGX_FPrintF(this->req.out, "\n"); - data = chunk_create(addr, sb.st_size); - - while (data.len) + while (data->len) { - written = FCGX_PutStr(data.ptr, data.len, this->req.out); + written = FCGX_PutStr(data->ptr, data->len, this->req.out); if (written == -1) { - munmap(addr, sb.st_size); - close(fd); + chunk_unmap(data); return FALSE; } - data = chunk_skip(data, written); + *data = chunk_skip(*data, written); } - munmap(addr, sb.st_size); - close(fd); + chunk_unmap(data); return TRUE; } From b8d0103e31ae6931fbb4365d6c63f78dc1e19513 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:47:23 +0100 Subject: [PATCH 07/11] radattr: Use chunk_map() instead of non-portable mmap() --- .../plugins/radattr/radattr_listener.c | 48 ++++--------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/src/libcharon/plugins/radattr/radattr_listener.c b/src/libcharon/plugins/radattr/radattr_listener.c index 5443800e5..3ce38ed12 100644 --- a/src/libcharon/plugins/radattr/radattr_listener.c +++ b/src/libcharon/plugins/radattr/radattr_listener.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -110,10 +109,7 @@ static void add_radius_attribute(private_radattr_listener_t *this, identification_t *id; auth_cfg_t *auth; char path[PATH_MAX]; - chunk_t data; - struct stat sb; - void *addr; - int fd; + chunk_t *data; auth = ike_sa->get_auth_cfg(ike_sa, TRUE); id = auth->get(auth, AUTH_RULE_EAP_IDENTITY); @@ -123,44 +119,16 @@ static void add_radius_attribute(private_radattr_listener_t *this, } snprintf(path, sizeof(path), "%s/%Y", this->dir, id); - fd = open(path, O_RDONLY); - if (fd != -1) + data = chunk_map(path, FALSE); + if (data) { - if (fstat(fd, &sb) != -1) + if (data->len >= 2) { - if (sb.st_size <= MAX_ATTR_SIZE) - { - addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr != MAP_FAILED) - { - data = chunk_create(addr, sb.st_size); - if (data.len >= 2) - { - DBG1(DBG_CFG, "adding RADIUS %N attribute", - radius_attribute_type_names, data.ptr[0]); - message->add_notify(message, FALSE, - RADIUS_ATTRIBUTE, data); - } - munmap(addr, sb.st_size); - } - else - { - DBG1(DBG_CFG, "mapping RADIUS attribute '%s' failed: %s", - path, strerror(errno)); - } - } - else - { - DBG1(DBG_CFG, "RADIUS attribute '%s' exceeds size limit", - path); - } + DBG1(DBG_CFG, "adding RADIUS %N attribute", + radius_attribute_type_names, data->ptr[0]); + message->add_notify(message, FALSE, RADIUS_ATTRIBUTE, *data); } - else - { - DBG1(DBG_CFG, "fstat RADIUS attribute '%s' failed: %s", - path, strerror(errno)); - } - close(fd); + chunk_unmap(data); } else { From ecdef634aac5e71c303525a5cf9b4e5f4029d8d5 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:48:03 +0100 Subject: [PATCH 08/11] stroke: Use chunk_map() instead of non-portable mmap() --- src/libcharon/plugins/stroke/stroke_cred.c | 36 ++++------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 224dd9803..43e5739b2 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -1101,46 +1100,24 @@ static bool load_shared(mem_cred_t *secrets, chunk_t line, int line_nr, static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, char *file, int level, FILE *prompt) { - int line_nr = 0, fd; - chunk_t src, line; - struct stat sb; - void *addr; + int line_nr = 0; + chunk_t *src, line; DBG1(DBG_CFG, "loading secrets from '%s'", file); - fd = open(file, O_RDONLY); - if (fd == -1) + src = chunk_map(file, FALSE); + if (!src) { DBG1(DBG_CFG, "opening secrets file '%s' failed: %s", file, strerror(errno)); return; } - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, "getting file size of '%s' failed: %s", file, - strerror(errno)); - close(fd); - return; - } - if (sb.st_size == 0) - { /* skip empty files, as mmap() complains */ - close(fd); - return; - } - addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, "mapping '%s' failed: %s", file, strerror(errno)); - close(fd); - return; - } - src = chunk_create(addr, sb.st_size); if (!secrets) { secrets = mem_cred_create(); } - while (fetchline(&src, &line)) + while (fetchline(src, &line)) { chunk_t ids, token; shared_key_type_t type; @@ -1281,8 +1258,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, break; } } - munmap(addr, sb.st_size); - close(fd); + chunk_unmap(src); if (level == 0) { /* replace secrets in active credential set */ From 88fa7f62bed4d1cfd6ed4ec88336a417478b402e Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:49:37 +0100 Subject: [PATCH 09/11] pem: Use chunk_map() instead of non-portable mmap() --- src/libstrongswan/plugins/pem/pem_builder.c | 35 ++++----------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c index 254b1951b..62780c384 100644 --- a/src/libstrongswan/plugins/pem/pem_builder.c +++ b/src/libstrongswan/plugins/pem/pem_builder.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -418,39 +417,17 @@ static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype, static void *load_from_file(char *file, credential_type_t type, int subtype, identification_t *subject, x509_flag_t flags) { - void *cred = NULL; - struct stat sb; - void *addr; - int fd; + void *cred; + chunk_t *chunk; - fd = open(file, O_RDONLY); - if (fd == -1) + chunk = chunk_map(file, FALSE); + if (!chunk) { DBG1(DBG_LIB, " opening '%s' failed: %s", file, strerror(errno)); return NULL; } - - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, " getting file size of '%s' failed: %s", file, - strerror(errno)); - close(fd); - return NULL; - } - - addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, " mapping '%s' failed: %s", file, strerror(errno)); - close(fd); - return NULL; - } - - cred = load_from_blob(chunk_create(addr, sb.st_size), type, subtype, - subject, flags); - - munmap(addr, sb.st_size); - close(fd); + cred = load_from_blob(*chunk, type, subtype, subject, flags); + chunk_unmap(chunk); return cred; } From 7ae878c3573c50c34c7a1b7941ddcffdae1f68a6 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:49:57 +0100 Subject: [PATCH 10/11] tnccs: Use chunk_map() instead of non-portable mmap() --- .../plugins/tnc_imv/tnc_imv_manager.c | 1 - src/libtnccs/tnc/tnc.c | 32 ++++--------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c index b4f131b5d..12ea20319 100644 --- a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c +++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/src/libtnccs/tnc/tnc.c b/src/libtnccs/tnc/tnc.c index 3a5b84596..fdf0412d1 100644 --- a/src/libtnccs/tnc/tnc.c +++ b/src/libtnccs/tnc/tnc.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -94,10 +93,8 @@ void libtnccs_deinit(void) static bool load_imcvs_from_config(char *filename, bool is_imc) { bool success = FALSE; - int fd, line_nr = 0; - chunk_t src, line; - struct stat sb; - void *addr; + int line_nr = 0; + chunk_t *src, line; char *label; if (!filename || !*filename) @@ -108,30 +105,15 @@ static bool load_imcvs_from_config(char *filename, bool is_imc) label = is_imc ? "IMC" : "IMV"; DBG1(DBG_TNC, "loading %ss from '%s'", label, filename); - fd = open(filename, O_RDONLY); - if (fd == -1) + src = chunk_map(filename, FALSE); + if (!src) { DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, strerror(errno)); return FALSE; } - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, - strerror(errno)); - close(fd); - return FALSE; - } - addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); - close(fd); - return FALSE; - } - src = chunk_create(addr, sb.st_size); - while (fetchline(&src, &line)) + while (fetchline(src, &line)) { char *name, *path; chunk_t token; @@ -201,8 +183,7 @@ static bool load_imcvs_from_config(char *filename, bool is_imc) break; } } - munmap(addr, sb.st_size); - close(fd); + chunk_unmap(src); return success; } @@ -272,4 +253,3 @@ bool tnc_manager_register(plugin_t *plugin, plugin_feature_t *feature, } return TRUE; } - From 853498155e88d63b062a8567f8439efefdcd2f5d Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 21 Nov 2013 14:49:19 +0100 Subject: [PATCH 11/11] libpts: Use chunk_map() instead of non-portable mmap() --- src/libpts/swid/swid_inventory.c | 34 +++++--------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/src/libpts/swid/swid_inventory.c b/src/libpts/swid/swid_inventory.c index a689ccdaa..a71682f43 100644 --- a/src/libpts/swid/swid_inventory.c +++ b/src/libpts/swid/swid_inventory.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -178,40 +177,19 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, if (this->full_tags) { swid_tag_t *tag; - chunk_t xml_tag; - struct stat sb; - void *addr; - int fd; + chunk_t *xml_tag; - fd = open(abs_name, O_RDONLY); - if (fd == -1) + xml_tag = chunk_map(abs_name, FALSE); + if (!xml_tag) { DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name, strerror(errno)); goto end; } - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_IMC, " getting file size of '%s' failed: %s", abs_name, - strerror(errno)); - close(fd); - goto end; - } - - addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_IMC, " mapping '%s' failed: %s", abs_name, - strerror(errno)); - close(fd); - goto end; - } - xml_tag = chunk_create(addr, sb.st_size); - tag = swid_tag_create(xml_tag, unique_seq_id); + tag = swid_tag_create(*xml_tag, unique_seq_id); this->list->insert_last(this->list, tag); - munmap(addr, sb.st_size); - close(fd); + chunk_unmap(xml_tag); } else { @@ -290,5 +268,3 @@ swid_inventory_t *swid_inventory_create(bool full_tags) return &this->public; } - -