1 /*
2  * dpkg - main program for package management
3  * force.c - force operation support
4  *
5  * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2006-2019 Guillem Jover <guillem@debian.org>
7  *
8  * This is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <compat.h>
24 
25 #include <errno.h>
26 #include <string.h>
27 #include <stdbool.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 
32 #include <dpkg/macros.h>
33 #include <dpkg/i18n.h>
34 #include <dpkg/dpkg.h>
35 #include <dpkg/dpkg-db.h>
36 #include <dpkg/options.h>
37 
38 #include "force.h"
39 
40 static int force_mask;
41 static int force_flags;
42 
43 enum forcetype {
44 	FORCETYPE_DISABLED,
45 	FORCETYPE_ENABLED,
46 	FORCETYPE_DAMAGE,
47 };
48 
49 static const char *
forcetype_str(enum forcetype type)50 forcetype_str(enum forcetype type)
51 {
52 	switch (type) {
53 	case FORCETYPE_DISABLED:
54 		return "   ";
55 	case FORCETYPE_ENABLED:
56 		return "[*]";
57 	case FORCETYPE_DAMAGE:
58 		return "[!]";
59 	default:
60 		internerr("unknown force type '%d'", type);
61 	}
62 }
63 
64 static const struct forceinfo {
65 	const char *name;
66 	int flag;
67 	char type;
68 	const char *desc;
69 } forceinfos[] = {
70 	{
71 		"all",
72 		FORCE_ALL,
73 		FORCETYPE_DAMAGE,
74 		N_("Set all force options"),
75 	}, {
76 		"security-mac",
77 		FORCE_SECURITY_MAC,
78 		FORCETYPE_ENABLED,
79 		N_("Use MAC based security if available"),
80 	}, {
81 		"downgrade",
82 		FORCE_DOWNGRADE,
83 		FORCETYPE_ENABLED,
84 		N_("Replace a package with a lower version"),
85 	}, {
86 		"configure-any",
87 		FORCE_CONFIGURE_ANY,
88 		FORCETYPE_DISABLED,
89 		N_("Configure any package which may help this one"),
90 	}, {
91 		"hold",
92 		FORCE_HOLD,
93 		FORCETYPE_DISABLED,
94 		N_("Process incidental packages even when on hold"),
95 	}, {
96 		"not-root",
97 		FORCE_NON_ROOT,
98 		FORCETYPE_DISABLED,
99 		N_("Try to (de)install things even when not root"),
100 	}, {
101 		"bad-path",
102 		FORCE_BAD_PATH,
103 		FORCETYPE_DISABLED,
104 		N_("PATH is missing important programs, problems likely"),
105 	}, {
106 		"bad-verify",
107 		FORCE_BAD_VERIFY,
108 		FORCETYPE_DISABLED,
109 		N_("Install a package even if it fails authenticity check"),
110 	}, {
111 		"bad-version",
112 		FORCE_BAD_VERSION,
113 		FORCETYPE_DISABLED,
114 		N_("Process even packages with wrong versions"),
115 	}, {
116 		"statoverride-add",
117 		FORCE_STATOVERRIDE_ADD,
118 		FORCETYPE_DISABLED,
119 		N_("Overwrite an existing stat override when adding it"),
120 	}, {
121 		"statoverride-remove",
122 		FORCE_STATOVERRIDE_DEL,
123 		FORCETYPE_DISABLED,
124 		N_("Ignore a missing stat override when removing it"),
125 	}, {
126 		"overwrite",
127 		FORCE_OVERWRITE,
128 		FORCETYPE_DISABLED,
129 		N_("Overwrite a file from one package with another"),
130 	}, {
131 		"overwrite-diverted",
132 		FORCE_OVERWRITE_DIVERTED,
133 		FORCETYPE_DISABLED,
134 		N_("Overwrite a diverted file with an undiverted version"),
135 	}, {
136 		"overwrite-dir",
137 		FORCE_OVERWRITE_DIR,
138 		FORCETYPE_DAMAGE,
139 		N_("Overwrite one package's directory with another's file"),
140 	}, {
141 		"unsafe-io",
142 		FORCE_UNSAFE_IO,
143 		FORCETYPE_DAMAGE,
144 		N_("Do not perform safe I/O operations when unpacking"),
145 	}, {
146 		"script-chrootless",
147 		FORCE_SCRIPT_CHROOTLESS,
148 		FORCETYPE_DAMAGE,
149 		N_("Do not chroot into maintainer script environment"),
150 	}, {
151 		"confnew",
152 		FORCE_CONFF_NEW,
153 		FORCETYPE_DAMAGE,
154 		N_("Always use the new config files, don't prompt"),
155 	}, {
156 		"confold",
157 		FORCE_CONFF_OLD,
158 		FORCETYPE_DAMAGE,
159 		N_("Always use the old config files, don't prompt"),
160 	}, {
161 		"confdef",
162 		FORCE_CONFF_DEF,
163 		FORCETYPE_DAMAGE,
164 		N_("Use the default option for new config files if one\n"
165 		   "is available, don't prompt. If no default can be found,\n"
166 		   "you will be prompted unless one of the confold or\n"
167 		   "confnew options is also given"),
168 	}, {
169 		"confmiss",
170 		FORCE_CONFF_MISS,
171 		FORCETYPE_DAMAGE,
172 		N_("Always install missing config files"),
173 	}, {
174 		"confask",
175 		FORCE_CONFF_ASK,
176 		FORCETYPE_DAMAGE,
177 		N_("Offer to replace config files with no new versions"),
178 	}, {
179 		"architecture",
180 		FORCE_ARCHITECTURE,
181 		FORCETYPE_DAMAGE,
182 		N_("Process even packages with wrong or no architecture"),
183 	}, {
184 		"breaks",
185 		FORCE_BREAKS,
186 		FORCETYPE_DAMAGE,
187 		N_("Install even if it would break another package"),
188 	}, {
189 		"conflicts",
190 		FORCE_CONFLICTS,
191 		FORCETYPE_DAMAGE,
192 		N_("Allow installation of conflicting packages"),
193 	}, {
194 		"depends",
195 		FORCE_DEPENDS,
196 		FORCETYPE_DAMAGE,
197 		N_("Turn all dependency problems into warnings"),
198 	}, {
199 		"depends-version",
200 		FORCE_DEPENDS_VERSION,
201 		FORCETYPE_DAMAGE,
202 		N_("Turn dependency version problems into warnings"),
203 	}, {
204 		"remove-reinstreq",
205 		FORCE_REMOVE_REINSTREQ,
206 		FORCETYPE_DAMAGE,
207 		N_("Remove packages which require installation"),
208 	}, {
209 		"remove-essential",
210 		FORCE_REMOVE_ESSENTIAL,
211 		FORCETYPE_DAMAGE,
212 		N_("Remove an essential package"),
213 	}, {
214 		NULL
215 	}
216 };
217 
218 bool
in_force(int flags)219 in_force(int flags)
220 {
221 	return (flags & force_flags) == flags;
222 }
223 
224 void
set_force(int flags)225 set_force(int flags)
226 {
227 	force_flags |= flags;
228 }
229 
230 void
reset_force(int flags)231 reset_force(int flags)
232 {
233 	force_flags &= ~flags;
234 }
235 
236 char *
get_force_string(void)237 get_force_string(void)
238 {
239 	const struct forceinfo *fip;
240 	struct varbuf vb = VARBUF_INIT;
241 
242 	for (fip = forceinfos; fip->name; fip++) {
243 		if ((enum force_flags)fip->flag == FORCE_ALL ||
244 		    (fip->flag & force_mask) != fip->flag ||
245 		    !in_force(fip->flag))
246 			continue;
247 
248 		if (vb.used)
249 			varbuf_add_char(&vb, ',');
250 		varbuf_add_str(&vb, fip->name);
251 	}
252 	varbuf_end_str(&vb);
253 
254 	return varbuf_detach(&vb);
255 }
256 
257 static inline void
print_forceinfo_line(int type,const char * name,const char * desc)258 print_forceinfo_line(int type, const char *name, const char *desc)
259 {
260 	printf("  %s %-18s %s\n", forcetype_str(type), name, desc);
261 }
262 
263 static void
print_forceinfo(const struct forceinfo * fi)264 print_forceinfo(const struct forceinfo *fi)
265 {
266 	char *desc, *line;
267 
268 	desc = m_strdup(gettext(fi->desc));
269 
270 	line = strtok(desc, "\n");
271 	print_forceinfo_line(fi->type, fi->name, line);
272 	while ((line = strtok(NULL, "\n")))
273 		print_forceinfo_line(FORCETYPE_DISABLED, "", line);
274 
275 	free(desc);
276 }
277 
278 void
parse_force(const char * value,bool set)279 parse_force(const char *value, bool set)
280 {
281 	const char *comma;
282 	size_t l;
283 	const struct forceinfo *fip;
284 
285 	if (strcmp(value, "help") == 0) {
286 		printf(_(
287 "%s forcing options - control behaviour when problems found:\n"
288 "  warn but continue:  --force-<thing>,<thing>,...\n"
289 "  stop with error:    --refuse-<thing>,<thing>,... | --no-force-<thing>,...\n"
290 " Forcing things:\n"), dpkg_get_progname());
291 
292 		for (fip = forceinfos; fip->name; fip++)
293 			if ((enum force_flags)fip->flag == FORCE_ALL ||
294 			    (fip->flag & force_mask) == fip->flag)
295 				print_forceinfo(fip);
296 
297 		printf(_(
298 "\n"
299 "WARNING - use of options marked [!] can seriously damage your installation.\n"
300 "Forcing options marked [*] are enabled by default.\n"));
301 		m_output(stdout, _("<standard output>"));
302 
303 		printf(_(
304 "\n"
305 "Currently enabled options:\n"
306 " %s\n"), get_force_string());
307 
308 		exit(0);
309 	}
310 
311 	for (;;) {
312 		comma = strchrnul(value, ',');
313 		l = (size_t)(comma - value);
314 		for (fip = forceinfos; fip->name; fip++)
315 			if (strncmp(fip->name, value, l) == 0 &&
316 			    strlen(fip->name) == l)
317 				break;
318 
319 		if (!fip->name) {
320 			badusage(_("unknown force/refuse option '%.*s'"),
321 			         (int)min(l, 250), value);
322 		} else if (fip->flag) {
323 			if (set)
324 				set_force(fip->flag);
325 			else
326 				reset_force(fip->flag);
327 		} else {
328 			warning(_("obsolete force/refuse option '%s'"),
329 			        fip->name);
330 		}
331 
332 		if (*comma == '\0')
333 			break;
334 		value = ++comma;
335 	}
336 }
337 
338 void
set_force_default(int mask)339 set_force_default(int mask)
340 {
341 	const char *force_env;
342 	const struct forceinfo *fip;
343 
344 	force_mask = mask;
345 
346 	/* If we get passed force options from the environment, do not
347 	 * initialize from the built-in defaults. */
348 	force_env = getenv("DPKG_FORCE");
349 	if (force_env != NULL) {
350 		if (force_env[0] != '\0')
351 			parse_force(force_env, 1);
352 		return;
353 	}
354 
355 	for (fip = forceinfos; fip->name; fip++)
356 		if (fip->type == FORCETYPE_ENABLED)
357 			set_force(fip->flag);
358 }
359 
360 void
set_force_option(const struct cmdinfo * cip,const char * value)361 set_force_option(const struct cmdinfo *cip, const char *value)
362 {
363 	bool set = cip->arg_int;
364 
365 	parse_force(value, set);
366 }
367 
368 void
reset_force_option(const struct cmdinfo * cip,const char * value)369 reset_force_option(const struct cmdinfo *cip, const char *value)
370 {
371 	reset_force(cip->arg_int);
372 }
373 
374 void
forcibleerr(int forceflag,const char * fmt,...)375 forcibleerr(int forceflag, const char *fmt, ...)
376 {
377 	va_list args;
378 
379 	va_start(args, fmt);
380 	if (in_force(forceflag)) {
381 		warning(_("overriding problem because --force enabled:"));
382 		warningv(fmt, args);
383 	} else {
384 		ohshitv(fmt, args);
385 	}
386 	va_end(args);
387 }
388 
389 int
forcible_nonroot_error(int rc)390 forcible_nonroot_error(int rc)
391 {
392 	if (in_force(FORCE_NON_ROOT) && errno == EPERM)
393 		return 0;
394 	return rc;
395 }
396