aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2009-11-22 21:57:18 -0800
committerAndrew G. Morgan <morgan@kernel.org>2009-11-22 22:00:53 -0800
commit7445469645b3587f0c8507504dc3889a013305e1 (patch)
treebefa1fdbe4395f37b3f8edaf8d1042e8935d2934
parentb0135454ab5365ab284465e8ad2830f92b3ea74c (diff)
downloadlibcap-7445469645b3587f0c8507504dc3889a013305e1.tar.gz
Checkpoint.
-rw-r--r--doc/Makefile6
-rw-r--r--doc/capsh.178
-rw-r--r--progs/capsh.c69
3 files changed, 149 insertions, 4 deletions
diff --git a/doc/Makefile b/doc/Makefile
index ba5ee92..5fe2189 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -5,6 +5,7 @@
topdir=$(shell pwd)/..
include $(topdir)/Make.Rules
+MAN1S = capsh.1
MAN3S = cap_init.3 cap_free.3 cap_dup.3 \
cap_clear.3 cap_clear_flag.3 cap_get_flag.3 cap_set_flag.3 \
cap_compare.3 cap_get_proc.3 cap_get_pid.3 cap_set_proc.3 \
@@ -14,7 +15,7 @@ MAN3S = cap_init.3 cap_free.3 cap_dup.3 \
capsetp.3 capgetp.3 libcap.3
MAN8S = getcap.8 setcap.8
-MANS = $(MAN3S) $(MAN8S)
+MANS = $(MAN1S) $(MAN3S) $(MAN8S)
all: $(MANS)
@@ -28,8 +29,9 @@ html:
done
install:
- mkdir -p -m 755 $(MANDIR)/man3 $(MANDIR)/man8
+ mkdir -p -m 755 $(MANDIR)/man1 $(MANDIR)/man3 $(MANDIR)/man8
for man in \
+ $(MANDIR)/man1 $(MAN1S) \
$(MANDIR)/man3 $(MAN3S) \
$(MANDIR)/man8 $(MAN8S) \
; \
diff --git a/doc/capsh.1 b/doc/capsh.1
new file mode 100644
index 0000000..20973b5
--- /dev/null
+++ b/doc/capsh.1
@@ -0,0 +1,78 @@
+.\"
+.\" capsh.1 Man page added 2009-11-22 Andrew G. Morgan <morgan@kernel.org>
+.\"
+.TH CAPSH 1 "2009-11-22" "libcap 2" "User Commands"
+.SH NAME
+capsh \- capability shell wrapper
+.SH SYNOPSIS
+.B capsh
+[\fIOPTION\fR]...
+.SH DESCRIPTION
+Linux capability support and use can be explored and constrained with
+this tool. This tool provides a handy wrapper for certain types
+of capability testing and environment creation. It also provides some
+debugging features useful for summarizing capability state.
+.SH OPTIONS
+The tool takes a number of optional arguments, acting on them in the
+order they are provided. They are as follows:
+.TP 22
+.B --print
+Display prevailing capability and related state.
+.TP
+.BI -- " [args]"
+Execute
+.B /bin/bash
+with trailing arguments. Note, you can use
+.B -c 'command to execute'
+for commands.
+.TP
+.B ==
+Execute
+.B capsh
+again with remaining arguments. Useful for testing
+.BR exec ()
+behavior.
+.TP
+.BI --caps= cap-set
+Set the prevailing process capabilities to those specified by
+.IR cap-set .
+Where
+.I cap-set
+is a text-representation of capability state as per
+.BR cap_from_text (3).
+.TP
+.BI --drop= <cap-list>
+.TP
+.BI --inh= <cap-list>
+.TP
+.BI --keep= <0|1>
+.TP
+.BI --chroot= <path>
+.TP
+.BI --secbits= <N>
+.TP
+.BI --forkfor= <sec>
+.TP
+.BI --killit= <sig>
+.TP
+.BI --uid= <id>
+.TP
+.BI --gid= <id>
+.TP
+.BI --groups= <gid-list>
+.TP
+.BI --user= <username>
+.TP
+.BI --decode= <N>
+.SH "EXIT STATUS"
+Following successful execution the tool exits with status 0. Following
+an error, the tool immediately exits with status 1.
+.SH AUTHOR
+Written by Andrew G. Morgan <morgan@kernel.org>.
+.SH "REPORTING BUGS"
+Please report bugs to the author.
+.SH "SEE ALSO"
+.BR libcap (3),
+.BR getcap (8), setcap (8)
+and
+.BR capabilities (7).
diff --git a/progs/capsh.c b/progs/capsh.c
index 40d632c..4cc3549 100644
--- a/progs/capsh.c
+++ b/progs/capsh.c
@@ -13,7 +13,10 @@
#include <string.h>
#include <stdlib.h>
#include <sys/prctl.h>
+#include <sys/types.h>
#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/capability.h>
@@ -26,6 +29,8 @@
#define PR_GET_SECUREBITS 27
#define PR_SET_SECUREBITS 28
+#define MAX_GROUPS 100 /* max number of supplementary groups for user */
+
static const cap_value_t raise_setpcap[1] = { CAP_SETPCAP };
static const cap_value_t raise_chroot[1] = { CAP_SYS_CHROOT };
@@ -311,6 +316,54 @@ int main(int argc, char *argv[], char *envp[])
value, strerror(errno));
exit(1);
}
+ } else if (!memcmp("--gid=", argv[i], 6)) {
+ unsigned value;
+ int status;
+
+ value = strtoul(argv[i]+6, NULL, 0);
+ status = setgid(value);
+ if (status < 0) {
+ fprintf(stderr, "Failed to set gid=%u: %s\n",
+ value, strerror(errno));
+ exit(1);
+ }
+ } else if (!memcmp("--groups=", argv[i], 9)) {
+ exit(1);
+ } else if (!memcmp("--user=", argv[i], 7)) {
+ struct passwd *pwd;
+ const char *user;
+ gid_t groups[MAX_GROUPS];
+ int status, ngroups;
+
+ user = argv[i] + 7;
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+ fprintf(stderr, "User [%s] not known\n", user);
+ exit(1);
+ }
+ ngroups = MAX_GROUPS;
+ status = getgrouplist(user, pwd->pw_gid, groups, &ngroups);
+ if (status < 1) {
+ perror("Unable to get group list for user");
+ exit(1);
+ }
+ status = setgroups(ngroups, groups);
+ if (status != 0) {
+ perror("Unable to set group list for user");
+ exit(1);
+ }
+ status = setgid(pwd->pw_gid);
+ if (status < 0) {
+ fprintf(stderr, "Failed to set gid=%u(user=%s): %s\n",
+ pwd->pw_gid, user, strerror(errno));
+ exit(1);
+ }
+ status = setuid(pwd->pw_uid);
+ if (status < 0) {
+ fprintf(stderr, "Failed to set uid=%u(user=%s): %s\n",
+ pwd->pw_uid, user, strerror(errno));
+ exit(1);
+ }
} else if (!memcmp("--decode=", argv[i], 9)) {
unsigned long long value;
unsigned cap;
@@ -337,10 +390,11 @@ int main(int argc, char *argv[], char *envp[])
printf("\n");
} else if (!strcmp("--print", argv[i])) {
unsigned cap;
- int set;
+ int set, status;
cap_t all;
char *text;
const char *sep;
+ gid_t groups[MAX_GROUPS];
all = cap_get_proc();
text = cap_to_text(all, NULL);
@@ -388,6 +442,15 @@ int main(int argc, char *argv[], char *envp[])
}
}
printf("uid=%u\n", getuid());
+ printf("gid=%u\n", getgid());
+ printf("groups=");
+ status = getgroups(MAX_GROUPS, groups);
+ sep = "";
+ for (i=0; i < status; i++) {
+ printf("%s%u", sep, groups[i]);
+ sep = ",";
+ }
+ printf("\n");
} else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i]))) {
argv[i] = strdup(argv[i][0] == '-' ? "/bin/bash" : argv[0]);
argv[argc] = NULL;
@@ -397,7 +460,7 @@ int main(int argc, char *argv[], char *envp[])
} else {
usage:
printf("usage: %s [args ...]\n"
- " --help this message\n"
+ " --help this message (or try 'man capsh')\n"
" --print display capability relevant state\n"
" --decode=xxx decode a hex string to a list of caps\n"
" --drop=xxx remove xxx,.. capabilities from bset\n"
@@ -406,6 +469,8 @@ int main(int argc, char *argv[], char *envp[])
" --secbits=<n> write a new value for securebits\n"
" --keep=<n> set keep-capabability bit to <n>\n"
" --uid=<n> set uid to <n> (hint: id <username>)\n"
+ " --gid=<n> set gid to <n> (hint: id <username>)\n"
+ " --user=<name> set uid,gid and groups to that of user\n"
" --chroot=path chroot(2) to this path to invoke bash\n"
" --killit=<n> send signal(n) to child\n"
" --forkfor=<n> fork and make child sleep for <n> sec\n"