t_setuid.c revision 261363
1284990Scy/*
2284990Scy * Copyright (c) 2001 Proofpoint, Inc. and its suppliers.
3284990Scy *	All rights reserved.
4284990Scy *
5289997Sglebius * By using this file, you agree to the terms and conditions set
6284990Scy * forth in the LICENSE file which can be found at the top level of
7284990Scy * the sendmail distribution.
8284990Scy *
9284990Scy */
10284990Scy
11284990Scy/*
12284990Scy**  This program checks to see if your version of setuid works.
13284990Scy**  Compile it, make it set-user-ID root, and run it as yourself (NOT as
14284990Scy**  root).
15284990Scy**
16284990Scy**	NOTE:  This should work everywhere, but Linux has the ability
17284990Scy**	to use the undocumented setcap() call to make this break.
18289997Sglebius**
19289997Sglebius**  Compilation is trivial -- just "cc t_setuid.c".  Make it set-user-ID,
20284990Scy**  root and then execute it as a non-root user.
21284990Scy*/
22284990Scy
23284990Scy#include <sys/types.h>
24289997Sglebius#include <unistd.h>
25289997Sglebius#include <stdio.h>
26284990Scy
27289997Sglebius#ifndef lint
28284990Scystatic char id[] = "@(#)$Id: t_setuid.c,v 8.8 2013/11/22 20:52:01 ca Exp $";
29284990Scy#endif /* ! lint */
30284990Scy
31289997Sglebiusstatic void
32289997Sglebiusprintuids(str, r, e)
33284990Scy	char *str;
34284990Scy	uid_t r, e;
35289997Sglebius{
36284990Scy	printf("%s (should be %d/%d): r/euid=%d/%d\n", str, (int) r, (int) e,
37284990Scy	       (int) getuid(), (int) geteuid());
38284990Scy}
39284990Scy
40284990Scyint
41284990Scymain(argc, argv)
42284990Scy	int argc;
43284990Scy	char **argv;
44284990Scy{
45284990Scy	int fail = 0;
46284990Scy	uid_t realuid = getuid();
47284990Scy
48284990Scy	printuids("initial uids", realuid, 0);
49284990Scy
50289997Sglebius	if (geteuid() != 0)
51284990Scy	{
52284990Scy		printf("SETUP ERROR: re-run set-user-ID root\n");
53284990Scy		exit(1);
54284990Scy	}
55284990Scy
56284990Scy	if (getuid() == 0)
57284990Scy	{
58289997Sglebius		printf("SETUP ERROR: must be run by a non-root user\n");
59284990Scy		exit(1);
60284990Scy	}
61284990Scy
62284990Scy	if (setuid(1) < 0)
63284990Scy		printf("setuid(1) failure\n");
64284990Scy	printuids("after setuid(1)", 1, 1);
65284990Scy
66289997Sglebius	if (geteuid() != 1)
67284990Scy	{
68284990Scy		fail++;
69284990Scy		printf("MAYDAY!  Wrong effective uid\n");
70284990Scy	}
71284990Scy
72284990Scy	if (getuid() != 1)
73284990Scy	{
74289997Sglebius		fail++;
75284990Scy		printf("MAYDAY!  Wrong real uid\n");
76284990Scy	}
77284990Scy
78289997Sglebius
79284990Scy	/* do activity here */
80284990Scy	if (setuid(0) == 0)
81284990Scy	{
82284990Scy		fail++;
83284990Scy		printf("MAYDAY!  setuid(0) succeeded (should have failed)\n");
84289997Sglebius	}
85284990Scy	else
86289997Sglebius	{
87289997Sglebius		printf("setuid(0) failed (this is correct)\n");
88289997Sglebius	}
89289997Sglebius	printuids("after setuid(0)", 1, 1);
90289997Sglebius
91284990Scy	if (geteuid() != 1)
92284990Scy	{
93289997Sglebius		fail++;
94284990Scy		printf("MAYDAY!  Wrong effective uid\n");
95284990Scy	}
96284990Scy	if (getuid() != 1)
97284990Scy	{
98284990Scy		fail++;
99284990Scy		printf("MAYDAY!  Wrong real uid\n");
100289997Sglebius	}
101284990Scy	printf("\n");
102284990Scy
103284990Scy	if (fail)
104284990Scy	{
105284990Scy		printf("\nThis system cannot use setuid (maybe use setreuid)\n");
106284990Scy		exit(1);
107284990Scy	}
108284990Scy
109289997Sglebius	printf("\nIt is safe to use setuid on this system\n");
110284990Scy	exit(0);
111289997Sglebius}
112284990Scy