898d1afbb9c5fbedb9ddc7d45a9ba9cc4071e876
[kai/samba.git] / lib / uid_wrapper / uid_wrapper.c
1 /*
2    Copyright (C) Andrew Tridgell 2009
3    Copyright (c) 2011      Andreas Schneider <asn@samba.org>
4  
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef _SAMBA_BUILD_
20
21 #define UID_WRAPPER_NOT_REPLACE
22 #include "replace.h"
23 #include "system/passwd.h"
24 #include <talloc.h>
25
26 #else /* _SAMBA_BUILD_ */
27
28 #error uid_wrapper_only_supported_in_samba_yet
29
30 #endif
31
32 #ifndef _PUBLIC_
33 #define _PUBLIC_
34 #endif
35
36 /*
37   we keep the virtualised euid/egid/groups information here
38  */
39 static struct {
40         bool initialised;
41         bool enabled;
42         uid_t myuid;
43         uid_t euid;
44         uid_t mygid;
45         gid_t egid;
46         gid_t *groups;
47 } uwrap;
48
49 static void uwrap_init(void)
50 {
51         if (uwrap.initialised) return;
52         uwrap.initialised = true;
53         if (getenv("UID_WRAPPER")) {
54                 uwrap.enabled = true;
55                 /* put us in one group */
56                 uwrap.myuid = uwrap.euid = geteuid();
57                 uwrap.mygid = uwrap.egid = getegid();
58                 uwrap.groups = talloc_array(NULL, gid_t, 1);
59                 uwrap.groups[0] = 0;
60         }
61 }
62
63 #undef uwrap_enabled
64 _PUBLIC_ int uwrap_enabled(void)
65 {
66         uwrap_init();
67         return uwrap.enabled?1:0;
68 }
69
70 #ifdef HAVE_SETEUID
71 _PUBLIC_ int uwrap_seteuid(uid_t euid)
72 {
73         uwrap_init();
74         if (!uwrap.enabled) {
75                 return seteuid(euid);
76         }
77         /* assume for now that the ruid stays as root */
78         if (euid == 0) {
79                 uwrap.euid = uwrap.myuid;
80         } else {
81                 uwrap.euid = euid;
82         }
83         return 0;
84 }
85 #endif
86
87 #ifdef HAVE_SETREUID
88 _PUBLIC_ int uwrap_setreuid(uid_t ruid, uid_t euid)
89 {
90         uwrap_init();
91         if (!uwrap.enabled) {
92                 return setreuid(ruid, euid);
93         }
94         /* assume for now that the ruid stays as root */
95         if (euid == 0) {
96                 uwrap.euid = uwrap.myuid;
97         } else {
98                 uwrap.euid = euid;
99         }
100         return 0;
101 }
102 #endif
103
104 #ifdef HAVE_SETRESUID
105 _PUBLIC_ int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
106 {
107         uwrap_init();
108         if (!uwrap.enabled) {
109                 return setresuid(ruid, euid, suid);
110         }
111         /* assume for now that the ruid stays as root */
112         if (euid == 0) {
113                 uwrap.euid = uwrap.myuid;
114         } else {
115                 uwrap.euid = euid;
116         }
117         return 0;
118 }
119 #endif
120
121 _PUBLIC_ uid_t uwrap_geteuid(void)
122 {
123         uwrap_init();
124         if (!uwrap.enabled) {
125                 return geteuid();
126         }
127         return uwrap.euid;
128 }
129
130 #ifdef HAVE_SETEGID
131 _PUBLIC_ int uwrap_setegid(gid_t egid)
132 {
133         uwrap_init();
134         if (!uwrap.enabled) {
135                 return setegid(egid);
136         }
137         /* assume for now that the ruid stays as root */
138         if (egid == 0) {
139                 uwrap.egid = uwrap.mygid;
140         } else {
141                 uwrap.egid = egid;
142         }
143         return 0;
144 }
145 #endif
146
147 #ifdef HAVE_SETREGID
148 _PUBLIC_ int uwrap_setregid(gid_t rgid, gid_t egid)
149 {
150         uwrap_init();
151         if (!uwrap.enabled) {
152                 return setregid(rgid, egid);
153         }
154         /* assume for now that the ruid stays as root */
155         if (egid == 0) {
156                 uwrap.egid = uwrap.mygid;
157         } else {
158                 uwrap.egid = egid;
159         }
160         return 0;
161 }
162 #endif
163
164 #ifdef HAVE_SETRESGID
165 _PUBLIC_ int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
166 {
167         uwrap_init();
168         if (!uwrap.enabled) {
169                 return setresgid(rgid, egid, sgid);
170         }
171         /* assume for now that the ruid stays as root */
172         if (egid == 0) {
173                 uwrap.egid = uwrap.mygid;
174         } else {
175                 uwrap.egid = egid;
176         }
177         return 0;
178 }
179 #endif
180
181 _PUBLIC_ uid_t uwrap_getegid(void)
182 {
183         uwrap_init();
184         if (!uwrap.enabled) {
185                 return getegid();
186         }
187         return uwrap.egid;
188 }
189
190 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
191 {
192         uwrap_init();
193         if (!uwrap.enabled) {
194                 return setgroups(size, list);
195         }
196
197         talloc_free(uwrap.groups);
198         uwrap.groups = NULL;
199
200         if (size != 0) {
201                 uwrap.groups = talloc_array(NULL, gid_t, size);
202                 if (uwrap.groups == NULL) {
203                         errno = ENOMEM;
204                         return -1;
205                 }
206                 memcpy(uwrap.groups, list, size*sizeof(gid_t));
207         }
208         return 0;
209 }
210
211 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
212 {
213         size_t ngroups;
214
215         uwrap_init();
216         if (!uwrap.enabled) {
217                 return getgroups(size, list);
218         }
219
220         ngroups = talloc_array_length(uwrap.groups);
221
222         if (size > ngroups) {
223                 size = ngroups;
224         }
225         if (size == 0) {
226                 return ngroups;
227         }
228         if (size < ngroups) {
229                 errno = EINVAL;
230                 return -1;
231         }
232         memcpy(list, uwrap.groups, size*sizeof(gid_t));
233         return ngroups;
234 }
235
236 _PUBLIC_ uid_t uwrap_getuid(void)
237 {
238         uwrap_init();
239         if (!uwrap.enabled) {
240                 return getuid();
241         }
242         /* we don't simulate ruid changing */
243         return 0;
244 }
245
246 _PUBLIC_ gid_t uwrap_getgid(void)
247 {
248         uwrap_init();
249         if (!uwrap.enabled) {
250                 return getgid();
251         }
252         /* we don't simulate rgid changing */
253         return 0;
254 }