diff options
author | rwatson <rwatson@FreeBSD.org> | 2002-06-13 23:40:13 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2002-06-13 23:40:13 +0000 |
commit | 98c2077a11dcaa1ca3ecd40d5031caccf347b452 (patch) | |
tree | dc3e6fd94d33f5d12453e45259019df9d095e8c8 /lib/libc/posix1e/cap_text.c | |
parent | 1f8d67dfae3bcd1b219934baf162c02edf8c7aa3 (diff) | |
download | FreeBSD-src-98c2077a11dcaa1ca3ecd40d5031caccf347b452.zip FreeBSD-src-98c2077a11dcaa1ca3ecd40d5031caccf347b452.tar.gz |
No POSIX.1e capabilities in the main tree yet.
Diffstat (limited to 'lib/libc/posix1e/cap_text.c')
-rw-r--r-- | lib/libc/posix1e/cap_text.c | 577 |
1 files changed, 0 insertions, 577 deletions
diff --git a/lib/libc/posix1e/cap_text.c b/lib/libc/posix1e/cap_text.c deleted file mode 100644 index 87a3080..0000000 --- a/lib/libc/posix1e/cap_text.c +++ /dev/null @@ -1,577 +0,0 @@ -/*- - * Copyright (c) 2000 Robert N. M. Watson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * TrustedBSD Project - support for POSIX.1e process capabilities - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include "namespace.h" -#include <sys/capability.h> -#include "un-namespace.h" -#include <sys/errno.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* - * this one is in sys/capability.h now: - * static const size_t CAP_MAX_BUF_LEN = 1024; - */ -static const size_t CAP_MAX_SMALL_BUF_LEN = 64; - -static const char *CAP_FLAGS[8] = { - "", /* 000 */ - "e", /* 001 */ - "i", /* 010 */ - "ei", /* 011 */ - "p", /* 100 */ - "ep", /* 101 */ - "ip", /* 110 */ - "eip", /* 111 */ -}; - -static const char *CAP_SEP = ": \t"; -static const char *CAP_OPERATION = "=-+"; - -struct cap_info { - char *ci_name; - cap_value_t ci_cap; -}; - -static const struct cap_info cap_info_array[] = { -{"CAP_CHOWN", CAP_CHOWN}, -{"CAP_DAC_EXECUTE", CAP_DAC_EXECUTE}, -{"CAP_DAC_WRITE", CAP_DAC_WRITE}, -{"CAP_DAC_READ_SEARCH", CAP_DAC_READ_SEARCH}, -{"CAP_FOWNER", CAP_FOWNER}, -{"CAP_FSETID", CAP_FSETID}, -{"CAP_KILL", CAP_KILL}, -{"CAP_LINK_DIR", CAP_LINK_DIR}, -{"CAP_SETFCAP", CAP_SETFCAP}, -{"CAP_SETGID", CAP_SETGID}, -{"CAP_SETUID", CAP_SETUID}, -{"CAP_MAC_DOWNGRADE", CAP_MAC_DOWNGRADE}, -{"CAP_MAC_READ", CAP_MAC_READ}, -{"CAP_MAC_RELABEL_SUBJ", CAP_MAC_RELABEL_SUBJ}, -{"CAP_MAC_UPGRADE", CAP_MAC_UPGRADE}, -{"CAP_MAC_WRITE", CAP_MAC_WRITE}, -{"CAP_INF_NOFLOAT_OBJ", CAP_INF_NOFLOAT_OBJ}, -{"CAP_INF_NOFLOAT_SUBJ", CAP_INF_NOFLOAT_SUBJ}, -{"CAP_INF_RELABEL_OBJ", CAP_INF_RELABEL_OBJ}, -{"CAP_INF_RELABEL_SUBJ", CAP_INF_RELABEL_SUBJ}, -{"CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL}, -{"CAP_AUDIT_WRITE", CAP_AUDIT_WRITE}, -{"CAP_SETPCAP", CAP_SETPCAP}, -{"CAP_SYS_SETFFLAG", CAP_SYS_SETFFLAG}, -{"CAP_LINUX_IMMUTABLE", CAP_SYS_SETFFLAG}, -{"CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE}, -{"CAP_NET_BROADCAST", CAP_NET_BROADCAST}, -{"CAP_NET_ADMIN", CAP_NET_ADMIN}, -{"CAP_NET_RAW", CAP_NET_RAW}, -{"CAP_IPC_LOCK", CAP_IPC_LOCK}, -{"CAP_IPC_OWNER", CAP_IPC_OWNER}, -{"CAP_SYS_MODULE", CAP_SYS_MODULE}, -{"CAP_SYS_RAWIO", CAP_SYS_RAWIO}, -{"CAP_SYS_CHROOT", CAP_SYS_CHROOT}, -{"CAP_SYS_PTRACE", CAP_SYS_PTRACE}, -{"CAP_SYS_PACCT", CAP_SYS_PACCT}, -{"CAP_SYS_ADMIN", CAP_SYS_ADMIN}, -{"CAP_SYS_BOOT", CAP_SYS_BOOT}, -{"CAP_SYS_NICE", CAP_SYS_NICE}, -{"CAP_SYS_RESOURCE", CAP_SYS_RESOURCE}, -{"CAP_SYS_TIME", CAP_SYS_TIME}, -{"CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG}, -{"CAP_MKNOD", CAP_MKNOD}, -{"", CAP_ALL_OFF}, -{"all", CAP_ALL_ON}, -}; - -static const int cap_info_array_len = sizeof(cap_info_array) / - sizeof(cap_info_array[0]); - -static const cap_value_t cap_list[] = { -CAP_CHOWN, -CAP_DAC_EXECUTE, -CAP_DAC_WRITE, -CAP_DAC_READ_SEARCH, -CAP_FOWNER, -CAP_FSETID, -CAP_KILL, -CAP_LINK_DIR, -CAP_SETFCAP, -CAP_SETGID, -CAP_SETUID, -CAP_MAC_DOWNGRADE, -CAP_MAC_READ, -CAP_MAC_RELABEL_SUBJ, -CAP_MAC_UPGRADE, -CAP_MAC_WRITE, -CAP_INF_NOFLOAT_OBJ, -CAP_INF_NOFLOAT_SUBJ, -CAP_INF_RELABEL_OBJ, -CAP_INF_RELABEL_SUBJ, -CAP_AUDIT_CONTROL, -CAP_AUDIT_WRITE, -CAP_SETPCAP, -CAP_SYS_SETFFLAG, -CAP_NET_BIND_SERVICE, -CAP_NET_BROADCAST, -CAP_NET_ADMIN, -CAP_NET_RAW, -CAP_IPC_LOCK, -CAP_IPC_OWNER, -CAP_SYS_MODULE, -CAP_SYS_RAWIO, -CAP_SYS_CHROOT, -CAP_SYS_PTRACE, -CAP_SYS_PACCT, -CAP_SYS_ADMIN, -CAP_SYS_BOOT, -CAP_SYS_NICE, -CAP_SYS_RESOURCE, -CAP_SYS_TIME, -CAP_SYS_TTY_CONFIG, -CAP_MKNOD, -}; - -static const int cap_list_len = sizeof(cap_list) / sizeof(cap_list[0]); - -static void -cap_set(cap_t cap_p, cap_flag_t flags, cap_flag_value_t fvalue, - cap_value_t cap_value) -{ - - if (flags & CAP_EFFECTIVE) { - if (fvalue == CAP_SET) - cap_p->c_effective |= cap_value; - else - cap_p->c_effective &= ~cap_value; - } - if (flags & CAP_INHERITABLE) { - if (fvalue == CAP_SET) - cap_p->c_inheritable |= cap_value; - else - cap_p->c_inheritable &= ~cap_value; - } - if (flags & CAP_PERMITTED) { - if (fvalue == CAP_SET) - cap_p->c_permitted |= cap_value; - else - cap_p->c_permitted &= ~cap_value; - } -} - -static int -cap_is_set(cap_t cap_p, cap_flag_t cap_flag, cap_value_t cap_value) -{ - int seen = 0; - - if (cap_flag & CAP_EFFECTIVE) - seen |= (cap_p->c_effective & cap_value); - if (cap_flag & CAP_INHERITABLE) - seen |= (cap_p->c_inheritable & cap_value); - if (cap_flag & CAP_PERMITTED) - seen |= (cap_p->c_permitted & cap_value); - - return (seen); -} - -static cap_flag_value_t -cap_value_to_flags(cap_t cap_p, cap_value_t cap_value) -{ - cap_flag_t flags = 0; - - if (cap_p->c_effective & cap_value) - flags |= CAP_EFFECTIVE; - if (cap_p->c_inheritable & cap_value) - flags |= CAP_INHERITABLE; - if (cap_p->c_permitted & cap_value) - flags |= CAP_PERMITTED; - - return (flags); -} - -static const char * -cap_flags_to_string(cap_flag_t flags) -{ - - return (CAP_FLAGS[flags]); -} - -static int -cap_string_to_flags(const char *string, cap_flag_t *flags) -{ - const char *c = string; - - *flags = 0; - while (*c != '\0') { - switch (*c) { - case 'e': - *flags |= CAP_EFFECTIVE; - break; - case 'i': - *flags |= CAP_INHERITABLE; - break; - case 'p': - *flags |= CAP_PERMITTED; - break; - default: - return (EINVAL); - } - c++; - } - - return (0); -} - -static const char * -cap_to_string(cap_value_t cap) -{ - int i; - - for (i = 0; i < cap_info_array_len; i++) { - if (cap_info_array[i].ci_cap == cap) - return (cap_info_array[i].ci_name); - } - - return (NULL); -} - -static int -cap_from_string(const char *string, cap_value_t *cap) -{ - int i; - - for (i = 0; i < cap_info_array_len; i++) { - if (!strcasecmp(cap_info_array[i].ci_name, string)) { - *cap = cap_info_array[i].ci_cap; - return (0); - } - } - - return (EINVAL); -} - -char * -cap_to_text(cap_t cap_p, ssize_t *len_p) -{ - cap_value_t cap_value; - cap_flag_t cap_flag, most_flag; - const char *flag_s, *value_s, *prefix_s; - char *buf, minibuf[CAP_MAX_SMALL_BUF_LEN], operation; - - int num_effective, num_inheritable, num_permitted; - int most_effective, most_inheritable, most_permitted; - int count, any_so_far; - - buf = (char *)malloc(CAP_MAX_BUF_LEN); - if (buf == NULL) { - errno = ENOMEM; - return (NULL); - } - buf[0] = '\0'; - - /* - * For the sake of prettiness, first walk each flag to see if it's - * set for cap_list_len/2 or more. If so, list it as a plus, and - * do the remainder as negative, as needed. This will tend to - * collapse a lot of the common all= cases. - */ - num_effective = num_inheritable = num_permitted = 0; - for (count = 0; count < cap_list_len; count++) { - cap_value = cap_list[count]; - if (cap_is_set(cap_p, CAP_EFFECTIVE, cap_value)) - num_effective++; - if (cap_is_set(cap_p, CAP_INHERITABLE, cap_value)) - num_inheritable++; - if (cap_is_set(cap_p, CAP_PERMITTED, cap_value)) - num_permitted++; - } - - most_effective = (num_effective > cap_list_len / 2); - most_inheritable = (num_inheritable > cap_list_len / 2); - most_permitted = (num_permitted > cap_list_len / 2); - - most_flag = 0; - if (most_effective) - most_flag |= CAP_EFFECTIVE; - if (most_inheritable) - most_flag |= CAP_INHERITABLE; - if (most_permitted) - most_flag |= CAP_PERMITTED; - - any_so_far = 0; - if (most_flag != 0) { - if ((strlcat(buf, "all=", CAP_MAX_BUF_LEN) >= - CAP_MAX_BUF_LEN) || - (strlcat(buf, CAP_FLAGS[most_flag], - CAP_MAX_BUF_LEN) >= CAP_MAX_BUF_LEN)) { - free(buf); - errno = ENOMEM; - return (NULL); - } - any_so_far = 1; - } - - /* - * For each capability value, determine how that value relates - * to the most common case, and (depending on CAP_PRINT_RELATIVE) - * either print out the value's flag set relative to the most - * common, or its absolute flag set. - */ - for (count = 0; count < cap_list_len; count++) { - cap_value = cap_list[count]; - cap_flag = cap_value_to_flags(cap_p, cap_value); - /* - * Determine which, if any, flags need to be printed - * for this capability. First, if the flags on the - * capability are equal to the "most" flags, just skip - * it. - */ - if (cap_flag == most_flag) - continue; - -#if CAP_PRINT_RELATIVE - /* - * If the flags are a strict superset of the "most" - * flags, print it as a "+" case. If they're a - * strict subset, print as a "-" case. Otherwise, - * specify as an "=" case. - */ - if ((cap_flag | most_flag) == cap_flag) { - /* Strict superset, use "+". */ - operation = '+'; - cap_flag = cap_flag & ~most_flag; - flag_s = cap_flags_to_string(cap_flag); - } else if ((cap_flag | most_flag) == most_flag) { - /* Strict subset, use "-". */ - operation = '-'; - cap_flag = most_flag & ~cap_flag; - flag_s = cap_flags_to_string(cap_flag); - } else { -#endif - /* Mixed, use an "=" case */ - operation = '='; - flag_s = cap_flags_to_string(cap_flag); -#if CAP_PRINT_RELATIVE - } -#endif - /* - * Now assemble clause, and append to the string being - * built. - */ - if (any_so_far) - prefix_s = ":"; - else - prefix_s = ""; - value_s = cap_to_string(cap_value); - if ((snprintf(minibuf, sizeof(minibuf), "%s%s%c%s", prefix_s, - value_s, operation, flag_s) >= sizeof(minibuf)) || - (strlcat(buf, minibuf, CAP_MAX_BUF_LEN) >= - CAP_MAX_BUF_LEN)) { - free(buf); - errno = ENOMEM; - return (NULL); - } - } - - if (len_p) - *len_p = strlen(buf); - return (buf); -} - -cap_t -cap_from_text(const char *buf_p) -{ - cap_value_t cap_value_v, cap_value_set_v; - cap_flag_t cap_action_v; - cap_t cap; - char *mybuf, *cur; - char *clause_s, *cap_value_s, *cap_value_list_s; - char *cap_action_list_s, *cap_action_s; - char *next_operation_p, operation, next_operation; - - cap = cap_init(); - if (cap == NULL) - return ((cap_t)NULL); - - mybuf = strdup(buf_p); - if (mybuf == NULL) { - errno = ENOMEM; - goto err1; - } - - /* - * clase [SEP clause [SEP clause ...]] - * Split into "clauses", which are separated by a : or whitespace. - * - * clause = [caplist]actionlist - * caplist = capabilityname[,capabilityname[, ...]] - * actionlist = op[flags][op[flags]] - * Split clauses into a (possibly null) capability name list, and a - * set of one or more {op,flags} pairs. - * - * Each assignment is then applied to a running "state" to - * produce an end-result in the internal representation. - * Parsing failure at any time releases resources and results - * in EINVAL. - */ - cur = mybuf; - while ((clause_s = strsep(&cur, CAP_SEP)) != NULL) { - /* - * Identify and NULL the first operation so that we - * can parse the capability name list, but save - * for later when we iterate over the operation list. - */ - cap_action_list_s = clause_s; - next_operation_p = strpbrk(cap_action_list_s, CAP_OPERATION); - if (next_operation_p == NULL) - goto err2; - operation = *next_operation_p; - cap_value_list_s = strsep(&cap_action_list_s, CAP_OPERATION); - if (cap_value_list_s == NULL || cap_action_list_s == NULL) - goto err2; - /* - * cap_value_list_s now points at the NULL-terminated list - * of capability values, if any. - * cap_action_list_s now points to the NULL-terminated list - * of actions. - * - * First, parse the value list to generate a value set - * refering to the combined contents of the value list. - */ - cap_value_set_v = 0; - while ((cap_value_s = strsep(&cap_value_list_s, ",")) != NULL) { - /* - * Convert value string into internal representation. - * Reject if not a valid capability identifier. - */ - if (cap_from_string(cap_value_s, &cap_value_v)) - goto err2; - cap_value_set_v |= cap_value_v; - } - - /* - * While the current operation is non-0, parse its flags, - * apply the actions, and then repeat. The first set - * is assured above when the capability list is split off. - */ - while (operation != 0) { - /* - * Identify and save the next operation, then NULL - * it to find the end of the current flags. - */ - next_operation_p = strpbrk(cap_action_list_s, - CAP_OPERATION); - if (next_operation_p) - next_operation = *next_operation_p; - else - next_operation = 0; - cap_action_s = strsep(&cap_action_list_s, - CAP_OPERATION); - /* - * Convert string form of flags to internal - * representation, reject if not possible. - */ - if (cap_string_to_flags(cap_action_s, &cap_action_v)) - goto err2; - - /* - * Now, based on operation apply actionlist flags - * to the capability value set built earlier from - * the capability list. - */ - switch (operation) { - case '=': - /* - * Remove current flags for the value set, - * replace with new flags. - * - * Spec requires that an "=" operation with - * no value set be treated as an "=" operation - * with a value set equivilent to "all". - */ - if (cap_value_set_v == CAP_ALL_OFF) { - cap_set(cap, CAP_EFFECTIVE| - CAP_INHERITABLE|CAP_PERMITTED, - CAP_CLEAR, CAP_ALL_ON); - cap_set(cap, cap_action_v, CAP_SET, - CAP_ALL_ON); - } else { - cap_set(cap, CAP_EFFECTIVE| - CAP_INHERITABLE|CAP_PERMITTED, - CAP_CLEAR, cap_value_set_v); - cap_set(cap, cap_action_v, CAP_SET, - cap_value_set_v); - } - break; - case '+': - /* - * Add current flags to value set. - * - * Spec requires that a "+" operation with - * no value set be rejected. - */ - if (cap_value_set_v == CAP_ALL_OFF) - goto err2; - cap_set(cap, cap_action_v, CAP_SET, - cap_value_set_v); - break; - case '-': - /* - * Subtract current flags from value set. - * - * Spec requires that a "-" operation with - * no value set be treated as a "-" operation - * with a value set equivilent to "all". - */ - if (cap_value_set_v == CAP_ALL_OFF) - cap_set(cap, cap_action_v, CAP_CLEAR, - CAP_ALL_ON); - else - cap_set(cap, cap_action_v, CAP_CLEAR, - cap_value_set_v); - break; - default: - goto err2; - } - operation = next_operation; - } - } - - return (cap); - err2: - errno = EINVAL; - free(mybuf); - err1: - cap_free(cap); - return ((cap_t)NULL); -} - |