Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ffa257d

Browse files
committed
Initial revision
1 parent 2e5168c commit ffa257d

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

Misc/setuid-prog.c

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

0 commit comments

Comments
 (0)