8229fbbd58e422d2a5930f57834ddcdaa2aad10d
[mat/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.groups = talloc_array(NULL, gid_t, 1);
54                 uwrap.groups[0] = 0;
55         }
56 }
57
58 #undef uwrap_enabled
59 _PUBLIC_ int uwrap_enabled(void)
60 {
61         uwrap_init();
62         return uwrap.enabled?1:0;
63 }
64
65 _PUBLIC_ int uwrap_seteuid(uid_t euid)
66 {
67         uwrap_init();
68         if (!uwrap.enabled) {
69                 return seteuid(euid);
70         }
71         /* assume for now that the ruid stays as root */
72         uwrap.euid = euid;
73         return 0;
74 }
75
76 _PUBLIC_ int uwrap_setreuid(uid_t ruid, uid_t euid)
77 {
78         uwrap_init();
79         if (!uwrap.enabled) {
80                 return setreuid(ruid, euid);
81         }
82         /* assume for now that the ruid stays as root */
83         uwrap.euid = euid;
84         return 0;
85 }
86
87 _PUBLIC_ int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
88 {
89         uwrap_init();
90         if (!uwrap.enabled) {
91                 return setresuid(ruid, euid, suid);
92         }
93         /* assume for now that the ruid stays as root */
94         uwrap.euid = euid;
95         return 0;
96 }
97
98 _PUBLIC_ uid_t uwrap_geteuid(void)
99 {
100         uwrap_init();
101         if (!uwrap.enabled) {
102                 return geteuid();
103         }
104         return uwrap.euid;
105 }
106
107 _PUBLIC_ int uwrap_setegid(gid_t egid)
108 {
109         uwrap_init();
110         if (!uwrap.enabled) {
111                 return setegid(egid);
112         }
113         /* assume for now that the ruid stays as root */
114         uwrap.egid = egid;
115         return 0;
116 }
117
118 _PUBLIC_ int uwrap_setregid(gid_t rgid, gid_t egid)
119 {
120         uwrap_init();
121         if (!uwrap.enabled) {
122                 return setregid(rgid, egid);
123         }
124         /* assume for now that the ruid stays as root */
125         uwrap.egid = egid;
126         return 0;
127 }
128
129 _PUBLIC_ uid_t uwrap_getegid(void)
130 {
131         uwrap_init();
132         if (!uwrap.enabled) {
133                 return getegid();
134         }
135         return uwrap.egid;
136 }
137
138 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
139 {
140         uwrap_init();
141         if (!uwrap.enabled) {
142                 return setgroups(size, list);
143         }
144
145         talloc_free(uwrap.groups);
146         uwrap.groups = NULL;
147
148         if (size != 0) {
149                 uwrap.groups = talloc_array(NULL, gid_t, size);
150                 if (uwrap.groups == NULL) {
151                         errno = ENOMEM;
152                         return -1;
153                 }
154                 memcpy(uwrap.groups, list, size*sizeof(gid_t));
155         }
156         return 0;
157 }
158
159 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
160 {
161         size_t ngroups;
162
163         uwrap_init();
164         if (!uwrap.enabled) {
165                 return getgroups(size, list);
166         }
167
168         ngroups = talloc_array_length(uwrap.groups);
169
170         if (size > ngroups) {
171                 size = ngroups;
172         }
173         if (size == 0) {
174                 return ngroups;
175         }
176         if (size < ngroups) {
177                 errno = EINVAL;
178                 return -1;
179         }
180         memcpy(list, uwrap.groups, size*sizeof(gid_t));
181         return ngroups;
182 }
183
184 _PUBLIC_ uid_t uwrap_getuid(void)
185 {
186         uwrap_init();
187         if (!uwrap.enabled) {
188                 return getuid();
189         }
190         /* we don't simulate ruid changing */
191         return 0;
192 }
193
194 _PUBLIC_ gid_t uwrap_getgid(void)
195 {
196         uwrap_init();
197         if (!uwrap.enabled) {
198                 return getgid();
199         }
200         /* we don't simulate rgid changing */
201         return 0;
202 }