• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * filecap.c - A program that lists running processes with capabilities
3  * Copyright (c) 2009-10 Red Hat Inc., Durham, North Carolina.
4  * All Rights Reserved.
5  *
6  * This software may be freely redistributed and/or modified under the
7  * terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2, or (at your option) any
9  * later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING. If not, write to the
18  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * Authors:
21  *   Steve Grubb <sgrubb@redhat.com>
22  */
23 
24 #include "config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include "cap-ng.h"
30 #define __USE_GNU 1
31 #include <fcntl.h>
32 #define __USE_XOPEN_EXTENDED 1
33 #include <ftw.h>
34 
35 static int show_all = 0, header = 0, capabilities = 0, cremove = 0;
36 
usage(void)37 static void usage(void)
38 {
39 	fprintf(stderr,
40 	    "usage: filecap [-a | -d | /dir | /dir/file [cap1 cap2 ...] ]\n");
41 	exit(1);
42 }
43 
check_file(const char * fpath,const struct stat * sb,int typeflag_unused,struct FTW * s_unused)44 static int check_file(const char *fpath,
45 		const struct stat *sb,
46 		int typeflag_unused __attribute__ ((unused)),
47 		struct FTW *s_unused __attribute__ ((unused)))
48 {
49 	if (S_ISREG(sb->st_mode) == 0)
50 		return FTW_CONTINUE;
51 
52 	int fd = open(fpath, O_RDONLY|O_CLOEXEC);
53 	if (fd >= 0) {
54 		capng_results_t rc;
55 
56 		capng_clear(CAPNG_SELECT_BOTH);
57 		capng_get_caps_fd(fd);
58 		rc = capng_have_capabilities(CAPNG_SELECT_CAPS);
59 		if (rc > CAPNG_NONE) {
60 			if (header == 0) {
61 				header = 1;
62 				printf("%-20s capabilities\n", "file");
63 			}
64 			printf("%s     ", fpath);
65 			if (rc == CAPNG_FULL)
66 				printf("full");
67 			else
68 				capng_print_caps_text(CAPNG_PRINT_STDOUT,
69 						CAPNG_PERMITTED);
70 			printf("\n");
71 		}
72 		close(fd);
73 	}
74 	return FTW_CONTINUE;
75 }
76 
77 
78 // Use cases:
79 //  filecap
80 //  filecap -a
81 //  filecap /path/dir
82 //  filecap /path/file
83 //  filecap /path/file capability1 capability2 capability 3 ...
84 //
main(int argc,char * argv[])85 int main(int argc, char *argv[])
86 {
87 #if CAP_LAST_CAP < 31 || !defined (VFS_CAP_U32) || !defined (HAVE_ATTR_XATTR_H)
88 	printf("File based capabilities are not supported\n");
89 #else
90 	char *path_env, *path = NULL, *dir = NULL;
91 	struct stat sbuf;
92 	int nftw_flags = FTW_PHYS;
93 	int i;
94 
95 	if (argc >1) {
96 		for (i=1; i<argc; i++) {
97 			if (strcmp(argv[i], "-a") == 0) {
98 				show_all = 1;
99 				if (argc != 2)
100 					usage();
101 			} else if (strcmp(argv[i], "-d") == 0) {
102 				for (i=0; i<=CAP_LAST_CAP; i++) {
103 					const char *n =
104 						capng_capability_to_name(i);
105 					if (n == NULL)
106 						n = "unknown";
107 					printf("%s\n", n);
108 				}
109 				return 0;
110 			} else if (argv[i][0] == '/') {
111 				if (lstat(argv[i], &sbuf) != 0) {
112 					printf("Error checking path %s (%s)\n",
113 						argv[i], strerror(errno));
114 					exit(1);
115 				}
116 				// Clear all capabilities in case cap strings
117 				// follow. If we get a second file we err out
118 				// so this is safe
119 				if (S_ISREG(sbuf.st_mode) && path == NULL &&
120 								 dir == NULL) {
121 					path = argv[i];
122 					capng_clear(CAPNG_SELECT_BOTH);
123 				} else if (S_ISDIR(sbuf.st_mode) && path == NULL
124 								&& dir == NULL)
125 					dir = argv[i];
126 				else {
127 					printf("Must be one regular file or "
128 						"directory\n");
129 					exit(1);
130 				}
131 			} else {
132 				int cap = capng_name_to_capability(argv[i]);
133 				if (cap >= 0) {
134 					if (path == NULL)
135 						usage();
136 					capng_update(CAPNG_ADD,
137 						CAPNG_PERMITTED|CAPNG_EFFECTIVE,
138 						cap);
139 					capabilities = 1;
140 				} else if (strcmp("none", argv[i]) == 0) {
141 					capng_clear(CAPNG_SELECT_BOTH);
142 					capabilities = 1;
143 					cremove = 1;
144 				} else {
145 					printf("Unrecognized capability.\n");
146 					usage();
147 				}
148 			}
149 		}
150 	}
151 	if (path == NULL && dir == NULL && show_all == 0) {
152 		path_env = getenv("PATH");
153 		if (path_env != NULL) {
154 			path = strdup(path_env);
155 			for (dir=strtok(path,":"); dir!=NULL;
156 						dir=strtok(NULL,":")) {
157 				nftw(dir, check_file, 1024, nftw_flags);
158 			}
159 			free(path);
160 		}
161 	} else if (path == NULL && dir == NULL && show_all == 1) {
162 		// Find files
163 		nftw("/", check_file, 1024, nftw_flags);
164 	} else if (dir) {
165 		// Print out the dir
166 		nftw(dir, check_file, 1024, nftw_flags);
167 	}else if (path && capabilities == 0) {
168 		// Print out specific file
169 		check_file(path, &sbuf, 0, NULL);
170 	} else if (path && capabilities == 1) {
171 		// Write capabilities to file
172 		int fd = open(path, O_WRONLY|O_NOFOLLOW|O_CLOEXEC);
173 		if (fd < 0) {
174 			printf("Could not open %s for writing (%s)\n", path,
175 				strerror(errno));
176 			return 1;
177 		}
178 		capng_apply_caps_fd(fd);
179 		close(fd);
180 	}
181 #endif
182 	return 0;
183 }
184 
185