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