s4:UID wrapper - Make it work on older distributions
[ira/wip.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         unsigned ngroups;
44         gid_t *groups;
45 } uwrap;
46
47 static void uwrap_init(void)
48 {
49         if (uwrap.initialised) return;
50         uwrap.initialised = true;
51         if (getenv("UID_WRAPPER")) {
52                 uwrap.enabled = true;
53                 /* put us in one group */
54                 uwrap.ngroups = 1;
55                 uwrap.groups = talloc_array(talloc_autofree_context(), 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_ uid_t uwrap_geteuid(void)
79 {
80         uwrap_init();
81         if (!uwrap.enabled) {
82                 return geteuid();
83         }
84         return uwrap.euid;
85 }
86
87 _PUBLIC_ int uwrap_setegid(gid_t egid)
88 {
89         uwrap_init();
90         if (!uwrap.enabled) {
91                 return setegid(egid);
92         }
93         /* assume for now that the ruid stays as root */
94         uwrap.egid = egid;
95         return 0;
96 }
97
98 _PUBLIC_ uid_t uwrap_getegid(void)
99 {
100         uwrap_init();
101         if (!uwrap.enabled) {
102                 return getegid();
103         }
104         return uwrap.egid;
105 }
106
107 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
108 {
109         uwrap_init();
110         if (!uwrap.enabled) {
111                 return setgroups(size, list);
112         }
113
114         talloc_free(uwrap.groups);
115         uwrap.ngroups = 0;
116         uwrap.groups = NULL;
117
118         if (size != 0) {
119                 uwrap.groups = talloc_array(talloc_autofree_context(), gid_t, size);
120                 if (uwrap.groups == NULL) {
121                         errno = ENOMEM;
122                         return -1;
123                 }
124                 memcpy(uwrap.groups, list, size*sizeof(gid_t));
125                 uwrap.ngroups = size;
126         }
127         return 0;
128 }
129
130 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
131 {
132         uwrap_init();
133         if (!uwrap.enabled) {
134                 return getgroups(size, list);
135         }
136
137         if (size > uwrap.ngroups) {
138                 size = uwrap.ngroups;
139         }
140         if (size == 0) {
141                 return uwrap.ngroups;
142         }
143         if (size < uwrap.ngroups) {
144                 errno = EINVAL;
145                 return -1;
146         }
147         memcpy(list, uwrap.groups, size*sizeof(gid_t));
148         return uwrap.ngroups;
149 }
150
151 _PUBLIC_ uid_t uwrap_getuid(void)
152 {
153         uwrap_init();
154         if (!uwrap.enabled) {
155                 return getuid();
156         }
157         /* we don't simulate ruid changing */
158         return 0;
159 }
160
161 _PUBLIC_ gid_t uwrap_getgid(void)
162 {
163         uwrap_init();
164         if (!uwrap.enabled) {
165                 return getgid();
166         }
167         /* we don't simulate rgid changing */
168         return 0;
169 }