diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-06-25 10:39:03 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-06-25 17:16:33 +0200 |
commit | 19375384403d08624a405a5e733d99bb5be62e2e (patch) | |
tree | a002d32515d1abac70645743a3134b3515972ac2 /src | |
parent | 9c354c659ffcd46507da76cdc6b29ee75dd216dd (diff) | |
download | strongswan-19375384403d08624a405a5e733d99bb5be62e2e.tar.bz2 strongswan-19375384403d08624a405a5e733d99bb5be62e2e.tar.xz |
capabilities: Handle CAP_CHOWN specially as it might not be required
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/utils/capabilities.c | 62 | ||||
-rw-r--r-- | src/libstrongswan/utils/capabilities.h | 3 |
2 files changed, 63 insertions, 2 deletions
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c index 98cd73832..10c67f106 100644 --- a/src/libstrongswan/utils/capabilities.c +++ b/src/libstrongswan/utils/capabilities.c @@ -76,6 +76,9 @@ struct private_capabilities_t { #endif }; +/** + * Verify that the current process has the given capability + */ static bool has_capability(u_int cap) { #ifndef CAPABILITIES @@ -120,8 +123,11 @@ static bool has_capability(u_int cap) #endif /* CAPABILITIES_NATIVE */ } -METHOD(capabilities_t, keep, bool, - private_capabilities_t *this, u_int cap) +/** + * Keep the given capability if it is held by the current process. Returns + * FALSE, if this is not the case. + */ +static bool keep_capability(private_capabilities_t *this, u_int cap) { if (!has_capability(cap)) { @@ -147,6 +153,58 @@ METHOD(capabilities_t, keep, bool, return TRUE; } +/** + * Returns TRUE if the current process/user is member of the given group + */ +static bool has_group(gid_t group) +{ + gid_t *groups; + long ngroups, i; + bool found = FALSE; + + if (group == getegid()) + { /* it's unspecified if this is part of the list below or not */ + return TRUE; + } + ngroups = sysconf(_SC_NGROUPS_MAX); + groups = calloc(ngroups, sizeof(gid_t)); + ngroups = getgroups(ngroups, groups); + if (ngroups == -1) + { + DBG1(DBG_LIB, "getting groups for current process failed: %s", + strerror(errno)); + return FALSE; + } + for (i = 0; i < ngroups; i++) + { + if (group == groups[i]) + { + found = TRUE; + break; + } + } + free(groups); + return found; +} + +METHOD(capabilities_t, keep, bool, + private_capabilities_t *this, u_int cap) +{ + if (cap == CAP_CHOWN) + { /* if new files/UNIX sockets are created they should be owned by the + * configured user and group. This requires a call to chown(2). But + * CAP_CHOWN is not always required. */ + if (!this->uid || geteuid() == this->uid) + { /* if the owner does not change CAP_CHOWN is not needed */ + if (!this->gid || has_group(this->gid)) + { /* the same applies if the owner is a member of the group */ + return TRUE; + } + } + } + return keep_capability(this, cap); +} + METHOD(capabilities_t, get_uid, uid_t, private_capabilities_t *this) { diff --git a/src/libstrongswan/utils/capabilities.h b/src/libstrongswan/utils/capabilities.h index 34937577a..4128909b6 100644 --- a/src/libstrongswan/utils/capabilities.h +++ b/src/libstrongswan/utils/capabilities.h @@ -32,6 +32,9 @@ typedef struct capabilities_t capabilities_t; # include <linux/capability.h> #endif +#ifndef CAP_CHOWN +# define CAP_CHOWN 0 +#endif #ifndef CAP_NET_BIND_SERVICE # define CAP_NET_BIND_SERVICE 10 #endif |