1 /*	$OpenBSD: privs.h,v 1.9 2004/06/17 22:09:11 millert Exp $	*/
2 
3 /*
4  *  privs.h - header for privileged operations
5  *  Copyright (C) 1993  Thomas Koenig
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author(s) may not be used to endorse or promote
13  *    products derived from this software without specific prior written
14  *    permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef _PRIVS_H
29 #define _PRIVS_H
30 
31 #include <unistd.h>
32 
33 /* Relinquish privileges temporarily for a setuid or setgid program
34  * with the option of getting them back later.  This is done by
35  * utilizing POSIX saved user and groups ids (or setreuid amd setregid if
36  * POSIX saved ids are not available).  Call RELINQUISH_PRIVS once
37  * at the beginning of the main program.  This will cause all operations
38  * to be executed with the real userid.  When you need the privileges
39  * of the setuid/setgid invocation, call PRIV_START; when you no longer
40  * need it, call PRIV_END.  Note that it is an error to call PRIV_START
41  * and not PRIV_END within the same function.
42  *
43  * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running
44  * as root, and you want to drop back the effective userid to a
45  * and the effective group id to b, with the option to get them back
46  * later.
47  *
48  * Problems: Do not use return between PRIV_START and PRIV_END; this
49  * will cause the program to continue running in an unprivileged
50  * state.
51  *
52  * It is NOT safe to call exec(), system() or popen() with a user-
53  * supplied program (i.e. without carefully checking PATH and any
54  * library load paths) with relinquished privileges; the called program
55  * can acquire them just as easily.  Set both effective and real userid
56  * to the real userid before calling any of them.
57  */
58 
59 #ifndef MAIN_PROGRAM
60 extern
61 #endif
62 uid_t real_uid, effective_uid;
63 
64 #ifndef MAIN_PROGRAM
65 extern
66 #endif
67 gid_t real_gid, effective_gid;
68 
69 #ifdef HAVE_SAVED_UIDS
70 
71 #define RELINQUISH_PRIVS do {			\
72       real_uid = getuid();			\
73       effective_uid = geteuid();		\
74       real_gid = getgid();			\
75       effective_gid = getegid();		\
76       setegid(real_gid);			\
77       seteuid(real_uid);			\
78 } while (0)
79 
80 #define RELINQUISH_PRIVS_ROOT(a, b) do {	\
81 	real_uid = (a);				\
82 	effective_uid = geteuid();		\
83 	real_gid = (b);				\
84 	effective_gid = getegid();		\
85 	setegid(real_gid);			\
86 	seteuid(real_uid);			\
87 } while (0)
88 
89 #define PRIV_START do {				\
90 	seteuid(effective_uid);			\
91 	setegid(effective_gid);			\
92 } while (0)
93 
94 #define PRIV_END do {				\
95 	setegid(real_gid);			\
96 	seteuid(real_uid);			\
97 } while (0)
98 
99 #else /* HAVE_SAVED_UIDS */
100 
101 #define RELINQUISH_PRIVS do {			\
102       real_uid = getuid();			\
103       effective_uid = geteuid();		\
104       real_gid = getgid();			\
105       effective_gid = getegid();		\
106       setregid(effective_gid, real_gid);	\
107       setreuid(effective_uid, real_uid);	\
108 } while (0)
109 
110 #define RELINQUISH_PRIVS_ROOT(a, b) do {	\
111 	real_uid = (a);				\
112 	effective_uid = geteuid();		\
113 	real_gid = (b);				\
114 	effective_gid = getegid();		\
115 	setregid(effective_gid, real_gid);	\
116 	setreuid(effective_uid, real_uid);	\
117 } while (0)
118 
119 #define PRIV_START do {				\
120 	setreuid(real_uid, effective_uid);	\
121 	setregid(real_gid, effective_gid);	\
122 } while (0)
123 
124 #define PRIV_END do {				\
125 	setregid(effective_gid, real_gid);	\
126 	setreuid(effective_uid, real_uid);	\
127 } while (0)
128 
129 #endif /* HAVE_SAVED_UIDS */
130 
131 #endif /* _PRIVS_H */
132