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