aboutsummaryrefslogtreecommitdiffstats
path: root/src/firecfg/desktop_files.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-09-25 07:38:01 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2017-09-25 07:38:01 -0400
commita6341b904c08b1feb51e264ab487d1f125222a10 (patch)
tree35ea50b8c8e561b710272a0e8ae9418541a32925 /src/firecfg/desktop_files.c
parentRemove whitelist from pinta (diff)
downloadfirejail-a6341b904c08b1feb51e264ab487d1f125222a10.tar.gz
firejail-a6341b904c08b1feb51e264ab487d1f125222a10.tar.zst
firejail-a6341b904c08b1feb51e264ab487d1f125222a10.zip
disable DBus activation in firecfg
Diffstat (limited to 'src/firecfg/desktop_files.c')
-rw-r--r--src/firecfg/desktop_files.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/src/firecfg/desktop_files.c b/src/firecfg/desktop_files.c
new file mode 100644
index 000000000..eaedc4b64
--- /dev/null
+++ b/src/firecfg/desktop_files.c
@@ -0,0 +1,265 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any 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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "firecfg.h"
22
23// look for a profile file in /etc/firejail diectory and in homedir/.config/firejail directory
24static int have_profile(const char *filename, const char *homedir) {
25 assert(filename);
26 assert(homedir);
27
28 if (arg_debug)
29 printf("checking profile for %s\n", filename);
30
31 // remove .desktop extension; if file name starts with org.gnome... remove it
32 char *f1;
33 if (strncmp(filename, "org.gnome.", 10) == 0)
34 f1 = strdup(filename + 10);
35 else
36 f1 = strdup(filename);
37 if (!f1)
38 errExit("strdup");
39 f1[strlen(f1) - 8] = '\0';
40 if (arg_debug)
41 printf("looking for a profile for %s - %s\n", filename, f1);
42
43 // build profile name
44 char *profname1;
45 char *profname2;
46 if (asprintf(&profname1, "%s/%s.profile", SYSCONFDIR, f1) == -1)
47 errExit("asprintf");
48 if (asprintf(&profname2, "%s/.config/firejail/%s.profile", homedir, f1) == -1)
49 errExit("asprintf");
50
51 int rv = 0;
52 if (access(profname1, R_OK) == 0) {
53 if (arg_debug)
54 printf("found %s\n", profname1);
55 rv = 1;
56 }
57 else if (access(profname2, R_OK) == 0) {
58 if (arg_debug)
59 printf("found %s\n", profname2);
60 rv = 1;
61 }
62
63 if (arg_debug)
64 printf("Profile for %s %s\n", f1, (rv)? "found": "not found");
65 free(f1);
66 free(profname1);
67 free(profname2);
68 return rv;
69}
70
71void fix_desktop_files(char *homedir) {
72 assert(homedir);
73 struct stat sb;
74
75 // check user
76 if (getuid() == 0) {
77 fprintf(stderr, "Error: this option is not supported for root user; please run as a regular user.\n");
78 exit(1);
79 }
80
81 // destination
82 // create ~/.local/share/applications directory if necessary
83 char *user_apps_dir;
84 if (asprintf(&user_apps_dir, "%s/.local/share/applications", homedir) == -1)
85 errExit("asprintf");
86 if (stat(user_apps_dir, &sb) == -1) {
87 int rv = mkdir(user_apps_dir, 0700);
88 if (rv) {
89 fprintf(stderr, "Error: cannot create ~/.local/application directory\n");
90 perror("mkdir");
91 exit(1);
92 }
93 rv = chmod(user_apps_dir, 0700);
94 (void) rv;
95 }
96
97 // source
98 DIR *dir = opendir("/usr/share/applications");
99 if (!dir) {
100 perror("Error: cannot open /usr/share/applications directory");
101 exit(1);
102 }
103 if (chdir("/usr/share/applications")) {
104 perror("Error: cannot chdir to /usr/share/applications");
105 exit(1);
106 }
107
108 printf("\nFixing desktop files in %s\n", user_apps_dir);
109 // copy
110 struct dirent *entry;
111 while ((entry = readdir(dir)) != NULL) {
112 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
113 continue;
114
115 // skip if not regular file or link
116 // d_type is not available on some file systems
117 if (entry->d_type != DT_REG && entry->d_type != DT_LNK && entry->d_type != DT_UNKNOWN)
118 continue;
119
120 // skip if not .desktop file
121 if (strstr(entry->d_name,".desktop") != (entry->d_name+strlen(entry->d_name)-8))
122 continue;
123
124 char *filename = entry->d_name;
125
126 // skip links
127 if (is_link(filename))
128 continue;
129 if (stat(filename, &sb) == -1)
130 errExit("stat");
131
132 // no profile in /etc/firejail, no desktop file fixing
133 if (!have_profile(filename, homedir))
134 continue;
135
136 //****************************************************
137 // load the file in memory and do some basic checking
138 //****************************************************
139 /* coverity[toctou] */
140 int fd = open(filename, O_RDONLY);
141 if (fd == -1) {
142 fprintf(stderr, "Error: cannot open /usr/share/applications/%s\n", filename);
143 continue;
144 }
145
146 char *buf = mmap(NULL, sb.st_size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
147 if (buf == MAP_FAILED)
148 errExit("mmap");
149 close(fd);
150
151 // check format
152 if (strstr(buf, "[Desktop Entry]\n") == NULL) {
153 if (arg_debug)
154 printf(" %s - skipped: wrong format?\n", filename);
155 munmap(buf, sb.st_size + 1);
156 continue;
157 }
158
159 // get executable name
160 char *ptr = strstr(buf,"\nExec=");
161 if (!ptr || strlen(ptr) < 7) {
162 if (arg_debug)
163 printf(" %s - skipped: wrong format?\n", filename);
164 munmap(buf, sb.st_size + 1);
165 continue;
166 }
167
168 char *execname = ptr + 6;
169 // executable name can be quoted, this is rare and currently unsupported, TODO
170 if (execname[0] == '"') {
171 if (arg_debug)
172 printf(" %s - skipped: path quoting unsupported\n", filename);
173 munmap(buf, sb.st_size + 1);
174 continue;
175 }
176
177
178 // try to decide if we need to covert this file
179 char *change_exec = NULL;
180 int change_dbus = 0;
181
182 // https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s06.html
183 // The executable program can either be specified with its full path
184 // or with the name of the executable only
185 if (execname[0] == '/') {
186 char *end_name = strchr(execname, ' ');
187 if (end_name) {
188 *end_name = '\0';
189 char *start_name = strrchr(execname, '/');
190 if (start_name) {
191 start_name++;
192 // check if we have the executable on the regular path
193 if (which(start_name)) {
194 change_exec = strdup(start_name);
195 if (!change_exec)
196 errExit("strdup");
197 }
198 }
199 }
200 }
201
202 if (strstr(buf, "\nDBusActivatable=true"))
203 change_dbus = 1;
204
205 if (change_exec == NULL && change_dbus == 0) {
206 munmap(buf, sb.st_size + 1);
207 continue;
208 }
209
210 munmap(buf, sb.st_size + 1);
211
212 //****************************************************
213 // generate output file
214 //****************************************************
215 char *outname;
216 if (asprintf(&outname ,"%s/%s", user_apps_dir, filename) == -1)
217 errExit("asprintf");
218
219 if (stat(outname, &sb) == 0) {
220 printf(" %s skipped: file exists\n", filename);
221 continue;
222 }
223
224 FILE *fpin = fopen(filename, "r");
225 if (!fpin) {
226 fprintf(stderr, "Error: cannot open /usr/share/applications/%s\n", filename);
227 continue;
228 }
229
230 FILE *fpout = fopen(outname, "w");
231 if (!fpout) {
232 fprintf(stderr, "Error: cannot open ~/.local/share/applications/%s\n", outname);
233 fclose(fpin);
234 continue;
235 }
236 fprintf(fpout, "# converted by firecfg\n");
237 free(outname);
238
239 char fbuf[MAX_BUF];
240 while (fgets(fbuf, MAX_BUF, fpin)) {
241 if (change_dbus && strcmp(fbuf, "DBusActivatable=true\n") == 0)
242 fprintf(fpout, "DBusActivatable=false\n");
243 else if (change_exec && strncmp(fbuf, "Exec=", 5) == 0) {
244 char *start_params = strchr(fbuf + 5, ' ');
245 assert(start_params);
246 start_params++;
247 fprintf(fpout, "Exec=%s %s", change_exec, start_params);
248 }
249 else
250 fprintf(fpout, "%s", fbuf);
251 }
252
253 if (change_exec)
254 free(change_exec);
255 fclose(fpin);
256 fclose(fpout);
257 printf(" %s created\n", filename);
258
259 }
260
261 closedir(dir);
262 free(user_apps_dir);
263}
264
265