summaryrefslogtreecommitdiffstats
path: root/lib/libc/posix1e/cap_text.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2002-06-13 23:40:13 +0000
committerrwatson <rwatson@FreeBSD.org>2002-06-13 23:40:13 +0000
commit98c2077a11dcaa1ca3ecd40d5031caccf347b452 (patch)
treedc3e6fd94d33f5d12453e45259019df9d095e8c8 /lib/libc/posix1e/cap_text.c
parent1f8d67dfae3bcd1b219934baf162c02edf8c7aa3 (diff)
downloadFreeBSD-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.c577
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);
-}
-
OpenPOWER on IntegriCloud