1/*
2 * Copyright (c) 2001 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11/*
12**  This program checks to see if your version of setgid works.
13**  Compile it, make it set-group-ID guest, and run it as yourself (NOT as
14**  root and not as member of the group guest).
15**
16**  Compilation is trivial -- just "cc t_dropgid.c".  Make it set-group-ID
17**  guest and then execute it as a non-root user.
18*/
19
20#include <sys/types.h>
21#include <unistd.h>
22#include <stdio.h>
23#include <stdlib.h>
24
25#ifndef lint
26static char id[] = "@(#)$Id: t_dropgid.c,v 1.7 2013-11-22 20:52:01 ca Exp $";
27#endif
28
29static void
30printgids(str, r, e)
31	char *str;
32	gid_t r, e;
33{
34	printf("%s (should be %d/%d): r/egid=%d/%d\n", str, (int) r, (int) e,
35	       (int) getgid(), (int) getegid());
36}
37
38/* define only one of these */
39#if HASSETEGID
40# define SETGIDCALL	"setegid"
41#endif
42#if HASSETREGID
43# define SETGIDCALL	"setregid"
44#endif
45#if HASSETRESGID
46# define SETGIDCALL	"setresgid"
47#endif
48
49#ifndef SETGIDCALL
50#  define SETGIDCALL	"setgid"
51#endif
52
53int
54main(argc, argv)
55	int argc;
56	char **argv;
57{
58	int fail = 0;
59	int res;
60	gid_t realgid = getgid();
61	gid_t effgid = getegid();
62	char *prg = argv[0];
63
64	printgids("initial gids", realgid, effgid);
65
66	if (effgid == realgid)
67	{
68		printf("SETUP ERROR: re-run set-group-ID guest\n");
69		printf("Use chgrp(1) and chmod(1)\n");
70		printf("For example, do this as root ");
71		printf("(nobody is the name of a group in this example):\n");
72		printf("# chgrp nobody %s\n", prg);
73		printf("# chmod g+s nobody %s\n", prg);
74		exit(1);
75	}
76
77#if HASSETREGID
78	res = setregid(realgid, realgid);
79	printf("setregid(%d)=%d %s\n", (int) realgid, res,
80		res < 0 ? "failure" : "ok");
81	printgids("after setregid()", realgid, realgid);
82#endif /* HASSETREGID */
83#if HASSETRESGID
84	res = setresgid(realgid, realgid, realgid);
85	printf("setresgid(%d)=%d %s\n", (int) realgid, res,
86		res < 0 ? "failure" : "ok");
87	printgids("after setresgid()", realgid, realgid);
88#endif /* HASSETRESGID */
89#if HASSETEGID
90	res = setegid(realgid);
91	printf("setegid(%d)=%d %s\n", (int) realgid, res,
92		res < 0 ? "failure" : "ok");
93	printgids("after setegid()", realgid, realgid);
94#endif /* HASSETEGID */
95	res = setgid(realgid);
96	printf("setgid(%d)=%d %s\n", (int) realgid, res,
97		res < 0 ? "failure" : "ok");
98	printgids("after setgid()", realgid, realgid);
99
100	if (getegid() != realgid)
101	{
102		fail++;
103		printf("MAYDAY!  Wrong effective gid\n");
104	}
105
106	if (getgid() != realgid)
107	{
108		fail++;
109		printf("MAYDAY!  Wrong real gid\n");
110	}
111
112	/* do activity here */
113	if (setgid(effgid) == 0)
114	{
115		fail++;
116		printf("MAYDAY!  setgid(%d) succeeded (should have failed)\n",
117			effgid);
118	}
119	else
120	{
121		printf("setgid(%d) failed (this is correct)\n", effgid);
122	}
123	printgids("after setgid() to egid", realgid, realgid);
124
125	if (getegid() != realgid)
126	{
127		fail++;
128		printf("MAYDAY!  Wrong effective gid\n");
129	}
130	if (getgid() != realgid)
131	{
132		fail++;
133		printf("MAYDAY!  Wrong real gid\n");
134	}
135	printf("\n");
136
137	if (fail > 0)
138	{
139		printf("\nThis system cannot use %s to give up set-group-ID rights\n",
140		       SETGIDCALL);
141#if !HASSETEGID
142		printf("Maybe compile with -DHASSETEGID and try again\n");
143#endif
144#if !HASSETREGID
145		printf("Maybe compile with -DHASSETREGID and try again\n");
146#endif
147#if !HASSETRESGID
148		printf("Maybe compile with -DHASSETRESGID and try again\n");
149#endif
150		exit(1);
151	}
152
153	printf("\nIt is possible to use %s on this system\n", SETGIDCALL);
154	exit(0);
155}
156