ยปCore Development>Code coverage>Misc/setuid-prog.c

Python code coverage for Misc/setuid-prog.c

#countcontent
1n/a/*
2n/a Template for a setuid program that calls a script.
3n/a
4n/a The script should be in an unwritable directory and should itself
5n/a be unwritable. In fact all parent directories up to the root
6n/a should be unwritable. The script must not be setuid, that's what
7n/a this program is for.
8n/a
9n/a This is a template program. You need to fill in the name of the
10n/a script that must be executed. This is done by changing the
11n/a definition of FULL_PATH below.
12n/a
13n/a There are also some rules that should be adhered to when writing
14n/a the script itself.
15n/a
16n/a The first and most important rule is to never, ever trust that the
17n/a user of the program will behave properly. Program defensively.
18n/a Check your arguments for reasonableness. If the user is allowed to
19n/a create files, check the names of the files. If the program depends
20n/a on argv[0] for the action it should perform, check it.
21n/a
22n/a Assuming the script is a Bourne shell script, the first line of the
23n/a script should be
24n/a #!/bin/sh -
25n/a The - is important, don't omit it. If you're using esh, the first
26n/a line should be
27n/a #!/usr/local/bin/esh -f
28n/a and for ksh, the first line should be
29n/a #!/usr/local/bin/ksh -p
30n/a The script should then set the variable IFS to the string
31n/a consisting of <space>, <tab>, and <newline>. After this (*not*
32n/a before!), the PATH variable should be set to a reasonable value and
33n/a exported. Do not expect the PATH to have a reasonable value, so do
34n/a not trust the old value of PATH. You should then set the umask of
35n/a the program by calling
36n/a umask 077 # or 022 if you want the files to be readable
37n/a If you plan to change directories, you should either unset CDPATH
38n/a or set it to a good value. Setting CDPATH to just ``.'' (dot) is a
39n/a good idea.
40n/a If, for some reason, you want to use csh, the first line should be
41n/a #!/bin/csh -fb
42n/a You should then set the path variable to something reasonable,
43n/a without trusting the inherited path. Here too, you should set the
44n/a umask using the command
45n/a umask 077 # or 022 if you want the files to be readable
46n/a*/
47n/a
48n/a#include <unistd.h>
49n/a#include <stdlib.h>
50n/a#include <stdio.h>
51n/a#include <sys/types.h>
52n/a#include <sys/stat.h>
53n/a#include <string.h>
54n/a
55n/a/* CONFIGURATION SECTION */
56n/a
57n/a#ifndef FULL_PATH /* so that this can be specified from the Makefile */
58n/a/* Uncomment the following line:
59n/a#define FULL_PATH "/full/path/of/script"
60n/a* Then comment out the #error line. */
61n/a#error "You must define FULL_PATH somewhere"
62n/a#endif
63n/a#ifndef UMASK
64n/a#define UMASK 077
65n/a#endif
66n/a
67n/a/* END OF CONFIGURATION SECTION */
68n/a
69n/a#if defined(__STDC__) && defined(__sgi)
70n/a#define environ _environ
71n/a#endif
72n/a
73n/a/* don't change def_IFS */
74n/achar def_IFS[] = "IFS= \t\n";
75n/a/* you may want to change def_PATH, but you should really change it in */
76n/a/* your script */
77n/a#ifdef __sgi
78n/achar def_PATH[] = "PATH=/usr/bsd:/usr/bin:/bin:/usr/local/bin:/usr/sbin";
79n/a#else
80n/achar def_PATH[] = "PATH=/usr/ucb:/usr/bin:/bin:/usr/local/bin";
81n/a#endif
82n/a/* don't change def_CDPATH */
83n/achar def_CDPATH[] = "CDPATH=.";
84n/a/* don't change def_ENV */
85n/achar def_ENV[] = "ENV=:";
86n/a
87n/a/*
88n/a This function changes all environment variables that start with LD_
89n/a into variables that start with XD_. This is important since we
90n/a don't want the script that is executed to use any funny shared
91n/a libraries.
92n/a
93n/a The other changes to the environment are, strictly speaking, not
94n/a needed here. They can safely be done in the script. They are done
95n/a here because we don't trust the script writer (just like the script
96n/a writer shouldn't trust the user of the script).
97n/a If IFS is set in the environment, set it to space,tab,newline.
98n/a If CDPATH is set in the environment, set it to ``.''.
99n/a Set PATH to a reasonable default.
100n/a*/
101n/avoid
102n/aclean_environ(void)
103n/a{
104n/a char **p;
105n/a extern char **environ;
106n/a
107n/a for (p = environ; *p; p++) {
108n/a if (strncmp(*p, "LD_", 3) == 0)
109n/a **p = 'X';
110n/a else if (strncmp(*p, "_RLD", 4) == 0)
111n/a **p = 'X';
112n/a else if (strncmp(*p, "PYTHON", 6) == 0)
113n/a **p = 'X';
114n/a else if (strncmp(*p, "IFS=", 4) == 0)
115n/a *p = def_IFS;
116n/a else if (strncmp(*p, "CDPATH=", 7) == 0)
117n/a *p = def_CDPATH;
118n/a else if (strncmp(*p, "ENV=", 4) == 0)
119n/a *p = def_ENV;
120n/a }
121n/a putenv(def_PATH);
122n/a}
123n/a
124n/aint
125n/amain(int argc, char **argv)
126n/a{
127n/a struct stat statb;
128n/a gid_t egid = getegid();
129n/a uid_t euid = geteuid();
130n/a
131n/a /*
132n/a Sanity check #1.
133n/a This check should be made compile-time, but that's not possible.
134n/a If you're sure that you specified a full path name for FULL_PATH,
135n/a you can omit this check.
136n/a */
137n/a if (FULL_PATH[0] != '/') {
138n/a fprintf(stderr, "%s: %s is not a full path name\n", argv[0],
139n/a FULL_PATH);
140n/a fprintf(stderr, "You can only use this wrapper if you\n");
141n/a fprintf(stderr, "compile it with an absolute path.\n");
142n/a exit(1);
143n/a }
144n/a
145n/a /*
146n/a Sanity check #2.
147n/a Check that the owner of the script is equal to either the
148n/a effective uid or the super user.
149n/a */
150n/a if (stat(FULL_PATH, &statb) < 0) {
151n/a perror("stat");
152n/a exit(1);
153n/a }
154n/a if (statb.st_uid != 0 && statb.st_uid != euid) {
155n/a fprintf(stderr, "%s: %s has the wrong owner\n", argv[0],
156n/a FULL_PATH);
157n/a fprintf(stderr, "The script should be owned by root,\n");
158n/a fprintf(stderr, "and shouldn't be writable by anyone.\n");
159n/a exit(1);
160n/a }
161n/a
162n/a if (setregid(egid, egid) < 0)
163n/a perror("setregid");
164n/a if (setreuid(euid, euid) < 0)
165n/a perror("setreuid");
166n/a
167n/a clean_environ();
168n/a
169n/a umask(UMASK);
170n/a
171n/a while (**argv == '-') /* don't let argv[0] start with '-' */
172n/a (*argv)++;
173n/a execv(FULL_PATH, argv);
174n/a fprintf(stderr, "%s: could not execute the script\n", argv[0]);
175n/a exit(1);
176n/a}