diff options
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r-- | src/libstrongswan/utils/capabilities.c | 60 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.c | 48 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.h | 15 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_builtin.c | 3 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_builtin.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_vstr.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils.c | 107 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils/string.c | 2 |
8 files changed, 190 insertions, 49 deletions
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c index 923b7d4db..ce5f550b5 100644 --- a/src/libstrongswan/utils/capabilities.c +++ b/src/libstrongswan/utils/capabilities.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Tobias Brunner + * Copyright (C) 2012-2015 Tobias Brunner * Hochschule fuer Technik Rapperswil * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG @@ -288,13 +288,25 @@ METHOD(capabilities_t, resolve_uid, bool, #ifdef HAVE_GETPWNAM_R struct passwd passwd; - char buf[1024]; + size_t buflen = 1024; + char *buf = NULL; - err = getpwnam_r(username, &passwd, buf, sizeof(buf), &pwp); - if (pwp) + while (TRUE) { - this->uid = pwp->pw_uid; + buf = realloc(buf, buflen); + err = getpwnam_r(username, &passwd, buf, buflen, &pwp); + if (err == ERANGE) + { + buflen *= 2; + continue; + } + if (pwp) + { + this->uid = pwp->pw_uid; + } + break; } + free(buf); #else /* HAVE GETPWNAM_R */ this->mutex->lock(this->mutex); pwp = getpwnam(username); @@ -324,13 +336,25 @@ METHOD(capabilities_t, resolve_gid, bool, #ifdef HAVE_GETGRNAM_R struct group group; - char buf[1024]; + size_t buflen = 1024; + char *buf = NULL; - err = getgrnam_r(groupname, &group, buf, sizeof(buf), &grp); - if (grp) + while (TRUE) { - this->gid = grp->gr_gid; + buf = realloc(buf, buflen); + err = getgrnam_r(groupname, &group, buf, buflen, &grp); + if (err == ERANGE) + { + buflen *= 2; + continue; + } + if (grp) + { + this->gid = grp->gr_gid; + } + break; } + free(buf); #else /* HAVE_GETGRNAM_R */ this->mutex->lock(this->mutex); grp = getgrnam(groupname); @@ -362,12 +386,24 @@ static bool init_supplementary_groups(private_capabilities_t *this) #ifdef HAVE_GETPWUID_R struct passwd pwd; - char buf[1024]; + size_t buflen = 1024; + char *buf = NULL; - if (getpwuid_r(this->uid, &pwd, buf, sizeof(buf), &pwp) == 0 && pwp) + while (TRUE) { - res = initgroups(pwp->pw_name, this->gid); + buf = realloc(buf, buflen); + if (getpwuid_r(this->uid, &pwd, buf, buflen, &pwp) == ERANGE) + { + buflen *= 2; + continue; + } + if (pwp) + { + res = initgroups(pwp->pw_name, this->gid); + } + break; } + free(buf); #else /* HAVE_GETPWUID_R */ this->mutex->lock(this->mutex); pwp = getpwuid(this->uid); diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index b69adf399..da23d143c 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 Tobias Brunner + * Copyright (C) 2009-2015 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -47,10 +47,9 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID, "ID_DER_ASN1_DN", "ID_DER_ASN1_GN", "ID_KEY_ID"); -ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_USER_ID, ID_KEY_ID, - "ID_DER_ASN1_GN_URI", - "ID_USER_ID"); -ENUM_END(id_type_names, ID_USER_ID); +ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID, + "ID_DER_ASN1_GN_URI"); +ENUM_END(id_type_names, ID_DER_ASN1_GN_URI); /** * coding of X.501 distinguished name @@ -478,7 +477,7 @@ static status_t atodn(char *src, chunk_t *dn) name.len -= whitespace; rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING && !asn1_is_printablestring(name)) - ? ASN1_T61STRING : x501rdns[i].type; + ? ASN1_UTF8STRING : x501rdns[i].type; if (rdn_count < RDN_MAX) { @@ -579,6 +578,19 @@ METHOD(identification_t, contains_wildcards_memchr, bool, return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL; } +METHOD(identification_t, hash_binary, u_int, + private_identification_t *this, u_int inc) +{ + u_int hash; + + hash = chunk_hash_inc(chunk_from_thing(this->type), inc); + if (this->type != ID_ANY) + { + hash = chunk_hash_inc(this->encoded, hash); + } + return hash; +} + METHOD(identification_t, equals_binary, bool, private_identification_t *this, identification_t *other) { @@ -687,6 +699,24 @@ METHOD(identification_t, equals_dn, bool, return compare_dn(this->encoded, other->get_encoding(other), NULL); } +METHOD(identification_t, hash_dn, u_int, + private_identification_t *this, u_int inc) +{ + enumerator_t *rdns; + chunk_t oid, data; + u_char type; + u_int hash; + + hash = chunk_hash_inc(chunk_from_thing(this->type), inc); + rdns = create_rdn_enumerator(this->encoded); + while (rdns->enumerate(rdns, &oid, &type, &data)) + { + hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash)); + } + rdns->destroy(rdns); + return hash; +} + METHOD(identification_t, equals_strcasecmp, bool, private_identification_t *this, identification_t *other) { @@ -828,7 +858,6 @@ int identification_printf_hook(printf_hook_data_t *data, case ID_FQDN: case ID_RFC822_ADDR: case ID_DER_ASN1_GN_URI: - case ID_USER_ID: chunk_printable(this->encoded, &proper, '?'); snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr); chunk_free(&proper); @@ -903,23 +932,26 @@ static private_identification_t *identification_create(id_type_t type) switch (type) { case ID_ANY: + this->public.hash = _hash_binary; this->public.matches = _matches_any; this->public.equals = _equals_binary; this->public.contains_wildcards = return_true; break; case ID_FQDN: case ID_RFC822_ADDR: - case ID_USER_ID: + this->public.hash = _hash_binary; this->public.matches = _matches_string; this->public.equals = _equals_strcasecmp; this->public.contains_wildcards = _contains_wildcards_memchr; break; case ID_DER_ASN1_DN: + this->public.hash = _hash_dn; this->public.equals = _equals_dn; this->public.matches = _matches_dn; this->public.contains_wildcards = _contains_wildcards_dn; break; default: + this->public.hash = _hash_binary; this->public.equals = _equals_binary; this->public.matches = _matches_binary; this->public.contains_wildcards = return_false; diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index e6a9fe1c6..5f27ba112 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Tobias Brunner + * Copyright (C) 2009-2015 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -129,11 +129,6 @@ enum id_type_t { * Private ID type which represents a GeneralName of type URI */ ID_DER_ASN1_GN_URI = 201, - - /** - * Private ID type which represents a user ID - */ - ID_USER_ID = 202 }; /** @@ -219,6 +214,14 @@ struct identification_t { id_type_t (*get_type) (identification_t *this); /** + * Create a hash value for this identification_t object. + * + * @param inc optional value for incremental hashing + * @return hash value + */ + u_int (*hash) (identification_t *this, u_int inc); + + /** * Check if two identification_t objects are equal. * * @param other other identification_t object diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c index 466c673d9..af5494052 100644 --- a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c +++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c @@ -843,7 +843,8 @@ int builtin_vsnprintf(char *buffer, size_t n, const char *format, va_list ap) /* String */ sarg = va_arg(ap, const char *); sarg = sarg ? sarg : "(null)"; - slen = strlen(sarg); + slen = prec != -1 ? strnlen(sarg, prec) + : strlen(sarg); goto is_string; } case 'm': diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h index 409b5bf3d..efbacff6f 100644 --- a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h +++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h @@ -15,7 +15,7 @@ /** * @defgroup printf_hook_builtin printf_hook_builtin - * @{ @ingroup utils + * @{ @ingroup printf_hook */ #ifndef PRINTF_HOOK_BUILTIN_H_ diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h index 2f9ee5983..7c24b05e2 100644 --- a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h +++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h @@ -16,7 +16,7 @@ /** * @defgroup printf_hook_vstr printf_hook_vstr - * @{ @ingroup utils + * @{ @ingroup printf_hook */ #ifndef PRINTF_HOOK_VSTR_H_ diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index 9b516accd..b4a4db802 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2014 Tobias Brunner + * Copyright (C) 2008-2015 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -16,15 +16,38 @@ #include "utils.h" +#include <sys/types.h> #include <unistd.h> #include <limits.h> +#include <ctype.h> #ifndef WIN32 # include <signal.h> #endif +#ifndef HAVE_CLOSEFROM +#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) +# include <sys/stat.h> +# include <fcntl.h> +# include <sys/syscall.h> +/* This is from the kernel sources. We limit the length of directory names to + * 256 as we only use it to enumerate FDs. */ +struct linux_dirent64 { + u_int64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; +#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */ +# include <dirent.h> +#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */ +#endif + #include <library.h> #include <collections/enumerator.h> +#define FD_DIR "/proc/self/fd" + #ifdef WIN32 #include <threading/mutex.h> @@ -110,43 +133,89 @@ void wait_sigint() /** * Described in header. */ -void closefrom(int lowfd) +void closefrom(int low_fd) { - char fd_dir[PATH_MAX]; - int maxfd, fd, len; + int max_fd, dir_fd, fd; /* try to close only open file descriptors on Linux... */ - len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid()); - if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0) +#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) + /* By directly using a syscall we avoid any calls that might be unsafe after + * fork() (e.g. malloc()). */ + char buffer[sizeof(struct linux_dirent64)]; + struct linux_dirent64 *entry; + int offset, len; + + dir_fd = open("/proc/self/fd", O_RDONLY); + if (dir_fd != -1) { - enumerator_t *enumerator = enumerator_create_directory(fd_dir); - if (enumerator) + while ((len = syscall(SYS_getdents64, dir_fd, buffer, + sizeof(buffer))) > 0) { - char *rel; - while (enumerator->enumerate(enumerator, &rel, NULL, NULL)) + for (offset = 0; offset < len; offset += entry->d_reclen) { - fd = atoi(rel); - if (fd >= lowfd) + entry = (struct linux_dirent64*)(buffer + offset); + if (!isdigit(entry->d_name[0])) + { + continue; + } + fd = atoi(entry->d_name); + if (fd != dir_fd && fd >= low_fd) { close(fd); } } - enumerator->destroy(enumerator); - return; } + close(dir_fd); + return; + } +#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */ + /* This is potentially unsafe when called after fork() in multi-threaded + * applications. In particular opendir() will require an allocation. + * Depends on how the malloc() implementation handles such situations. */ + DIR *dir; + struct dirent *entry; + +#ifndef HAVE_DIRFD + /* if we don't have dirfd() lets close the lowest FD and hope it gets reused + * by opendir() */ + close(low_fd); + dir_fd = low_fd++; +#endif + + dir = opendir(FD_DIR); + if (dir) + { +#ifdef HAVE_DIRFD + dir_fd = dirfd(dir); +#endif + while ((entry = readdir(dir))) + { + if (!isdigit(entry->d_name[0])) + { + continue; + } + fd = atoi(entry->d_name); + if (fd != dir_fd && fd >= low_fd) + { + close(fd); + } + } + closedir(dir); + return; } +#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */ /* ...fall back to closing all fds otherwise */ #ifdef WIN32 - maxfd = _getmaxstdio(); + max_fd = _getmaxstdio(); #else - maxfd = (int)sysconf(_SC_OPEN_MAX); + max_fd = (int)sysconf(_SC_OPEN_MAX); #endif - if (maxfd < 0) + if (max_fd < 0) { - maxfd = 256; + max_fd = 256; } - for (fd = lowfd; fd < maxfd; fd++) + for (fd = low_fd; fd < max_fd; fd++) { close(fd); } diff --git a/src/libstrongswan/utils/utils/string.c b/src/libstrongswan/utils/utils/string.c index 14087e765..56910ed79 100644 --- a/src/libstrongswan/utils/utils/string.c +++ b/src/libstrongswan/utils/utils/string.c @@ -44,7 +44,7 @@ char* translate(char *str, const char *from, const char *to) char* strreplace(const char *str, const char *search, const char *replace) { size_t len, slen, rlen, count = 0; - char *res, *pos, *found, *dst; + char *res, *pos, *found = NULL, *dst; if (!str || !*str || !search || !*search || !replace) { |