uid_wrapper: Add uwrap_setreuid().
[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_ uid_t uwrap_geteuid(void)
88 {
89         uwrap_init();
90         if (!uwrap.enabled) {
91                 return geteuid();
92         }
93         return uwrap.euid;
94 }
95
96 _PUBLIC_ int uwrap_setegid(gid_t egid)
97 {
98         uwrap_init();
99         if (!uwrap.enabled) {
100                 return setegid(egid);
101         }
102         /* assume for now that the ruid stays as root */
103         uwrap.egid = egid;
104         return 0;
105 }
106
107 _PUBLIC_ uid_t uwrap_getegid(void)
108 {
109         uwrap_init();
110         if (!uwrap.enabled) {
111                 return getegid();
112         }
113         return uwrap.egid;
114 }
115
116 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
117 {
118         uwrap_init();
119         if (!uwrap.enabled) {
120                 return setgroups(size, list);
121         }
122
123         talloc_free(uwrap.groups);
124         uwrap.groups = NULL;
125
126         if (size != 0) {
127                 uwrap.groups = talloc_array(NULL, gid_t, size);
128                 if (uwrap.groups == NULL) {
129                         errno = ENOMEM;
130                         return -1;
131                 }
132                 memcpy(uwrap.groups, list, size*sizeof(gid_t));
133         }
134         return 0;
135 }
136
137 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
138 {
139         size_t ngroups;
140
141         uwrap_init();
142         if (!uwrap.enabled) {
143                 return getgroups(size, list);
144         }
145
146         ngroups = talloc_array_length(uwrap.groups);
147
148         if (size > ngroups) {
149                 size = ngroups;
150         }
151         if (size == 0) {
152                 return ngroups;
153         }
154         if (size < ngroups) {
155                 errno = EINVAL;
156                 return -1;
157         }
158         memcpy(list, uwrap.groups, size*sizeof(gid_t));
159         return ngroups;
160 }
161
162 _PUBLIC_ uid_t uwrap_getuid(void)
163 {
164         uwrap_init();
165         if (!uwrap.enabled) {
166                 return getuid();
167         }
168         /* we don't simulate ruid changing */
169         return 0;
170 }
171
172 _PUBLIC_ gid_t uwrap_getgid(void)
173 {
174         uwrap_init();
175         if (!uwrap.enabled) {
176                 return getgid();
177         }
178         /* we don't simulate rgid changing */
179         return 0;
180 }