xref: /dragonfly/usr.bin/setcaps/setcaps.c (revision f9993810)
1 /*
2  * Copyright (c) 2023 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 /*
35  * setcaps - Set capability restrictions on the parent process of this
36  * 	     program (usually a shell).
37  */
38 #include <sys/types.h>
39 #include <sys/caps.h>
40 #include <errno.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 __SYSCAP_ALLSTRINGS;
47 
48 static void printallcaps(void);
49 static void listcaps(void);
50 
51 int
52 main(int ac, char **av)
53 {
54 	int quietopt = 0;
55 	int c;
56 	int i;
57 	int j;
58 	int estatus = 0;
59 	int noargs = 1;
60 
61 	while ((c = getopt(ac, av, "plqh")) != -1) {
62 		noargs = 0;
63 		switch(c) {
64 		case 'p':
65 			printallcaps();
66 			break;
67 		case 'l':
68 			listcaps();
69 			break;
70 		case 'q':
71 			quietopt = 1;
72 			break;
73 		case 'h':
74 		default:
75 			if (c != 'h')
76 				fprintf(stderr, "Bad option: -%c\n", c);
77 			fprintf(stderr, "setcaps [-p] [-l] caps...\n");
78 			fprintf(stderr, "    -p	- list available caps\n");
79 			fprintf(stderr, "    -l	- list current caps\n");
80 			fprintf(stderr, "    -q	- ignore unknown caps\n");
81 			fprintf(stderr, "  caps[:es] - set specific flags\n");
82 			fprintf(stderr, "  If no args, current caps are "
83 					"listed\n");
84 			if (c != 'h')
85 				exit(1);
86 			exit(0);
87 		}
88 	}
89 	ac -= optind;
90 	av += optind;
91 
92 	for (j = 0; j < ac; ++j) {
93 		char *which;
94 		char *scan;
95 		int res;
96 		int flags = __SYSCAP_SELF | __SYSCAP_EXEC;
97 		int found = 0;
98 
99 		noargs = 0;
100 
101 		which = av[j];
102 		if ((scan = strchr(which, ':')) != NULL) {
103 			*scan++ = 0;
104 			flags = 0;
105 			while (*scan) {
106 				switch (*scan) {
107 				case 's':
108 					flags |= __SYSCAP_SELF;
109 					break;
110 				case 'e':
111 					flags |= __SYSCAP_EXEC;
112 					break;
113 				default:
114 					fprintf(stderr, "unknown flag %s:%c\n",
115 						which, *scan);
116 					break;
117 				}
118 				++scan;
119 			}
120 		}
121 		for (i = 0; i < __SYSCAP_COUNT; ++i) {
122 			const char *ptr;
123 
124 			ptr = SyscapAllStrings[i / 16][i & 15];
125 			if (ptr == NULL || strcmp(ptr, which) != 0)
126 				continue;
127 			found = 1;
128 			res = syscap_set(i | __SYSCAP_INPARENT, flags, NULL, 0);
129 			if (res < 0) {
130 				fprintf(stderr, "%s: %s\n",
131 					which, strerror(errno));
132 				estatus = 1;
133 			} else {
134 				printf("%s: ", which);
135 				if (res & __SYSCAP_EXEC)
136 					printf(" on-exec");
137 				if (res & __SYSCAP_SELF)
138 					printf(" on-self");
139 				printf("\n");
140 			}
141 		}
142 		if (found == 0 && quietopt == 0) {
143 			printf("%s: not-found\n", which);
144 		}
145 	}
146 	if (noargs)
147 		listcaps();
148 
149 	return estatus;
150 }
151 
152 static void
153 printallcaps(void)
154 {
155 	const char *ptr;
156 	int i;
157 
158 	for (i = 0; i < __SYSCAP_COUNT; ++i) {
159 		if ((ptr = SyscapAllStrings[i / 16][i & 15]) != NULL) {
160 			printf("0x%04x %s\n", i, ptr);
161 		}
162 	}
163 }
164 
165 static void
166 listcaps(void)
167 {
168 	int i;
169 
170 	for (i = 0; i < __SYSCAP_COUNT; ++i) {
171 		const char *ptr;
172 		int res;
173 
174 		res = syscap_get(i | __SYSCAP_INPARENT, NULL, 0);
175 		if (res < 0)
176 			break;
177 		if (res) {
178 			if ((ptr = SyscapAllStrings[i / 16][i & 15]) != NULL) {
179 				printf("%-15s", ptr);
180 			} else {
181 				printf("0x%04x         ", res);
182 			}
183 			if (res & __SYSCAP_EXEC)
184 				printf(" on-exec");
185 			if (res & __SYSCAP_SELF)
186 				printf(" on-self");
187 			printf("\n");
188 		}
189 	}
190 }
191