make the UID_WRAPPER skip checks at runtime
[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 #define UID_WRAPPER_NOT_REPLACE
19 #include "includes.h"
20 #include "system/passwd.h"
21 #include "system/filesys.h"
22
23 #ifndef _PUBLIC_
24 #define _PUBLIC_
25 #endif
26
27 /*
28   we keep the virtualised euid/egid/groups information here
29  */
30 static struct {
31         bool initialised;
32         bool enabled;
33         uid_t euid;
34         gid_t egid;
35         unsigned ngroups;
36         gid_t *groups;
37 } uwrap;
38
39 static void uwrap_init(void)
40 {
41         if (uwrap.initialised) return;
42         uwrap.initialised = true;
43         if (getenv("UID_WRAPPER")) {
44                 uwrap.enabled = true;
45         }
46 }
47
48 #undef uwrap_enabled
49 _PUBLIC_ int uwrap_enabled(void)
50 {
51         uwrap_init();
52         return uwrap.enabled?1:0;
53 }
54
55 _PUBLIC_ int uwrap_seteuid(uid_t euid)
56 {
57         uwrap_init();
58         if (!uwrap.enabled) {
59                 return seteuid(euid);
60         }
61         /* assume for now that the ruid stays as root */
62         uwrap.euid = euid;
63         return 0;
64 }
65
66 _PUBLIC_ uid_t uwrap_geteuid(void)
67 {
68         uwrap_init();
69         if (!uwrap.enabled) {
70                 return geteuid();
71         }
72         return uwrap.euid;
73 }
74
75 _PUBLIC_ int uwrap_setegid(gid_t egid)
76 {
77         uwrap_init();
78         if (!uwrap.enabled) {
79                 return setegid(egid);
80         }
81         /* assume for now that the ruid stays as root */
82         uwrap.egid = egid;
83         return 0;
84 }
85
86 _PUBLIC_ uid_t uwrap_getegid(void)
87 {
88         uwrap_init();
89         if (!uwrap.enabled) {
90                 return getegid();
91         }
92         return uwrap.egid;
93 }
94
95 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
96 {
97         uwrap_init();
98         if (!uwrap.enabled) {
99                 return setgroups(size, list);
100         }
101
102         talloc_free(uwrap.groups);
103         uwrap.ngroups = 0;
104
105         uwrap.groups = talloc_array(talloc_autofree_context(), gid_t, size);
106         if (uwrap.groups == NULL) {
107                 errno = ENOMEM;
108                 return -1;
109         }
110         memcpy(uwrap.groups, list, size*sizeof(gid_t));
111         uwrap.ngroups = size;
112         return 0;
113 }
114
115 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
116 {
117         uwrap_init();
118         if (!uwrap.enabled) {
119                 return getgroups(size, list);
120         }
121
122         if (size > uwrap.ngroups) {
123                 size = uwrap.ngroups;
124         }
125         if (size == 0) {
126                 return uwrap.ngroups;
127         }
128         if (size < uwrap.ngroups) {
129                 errno = EINVAL;
130                 return -1;
131         }
132         memcpy(list, uwrap.groups, size*sizeof(gid_t));
133         return 0;
134 }
135
136 _PUBLIC_ uid_t uwrap_getuid(void)
137 {
138         uwrap_init();
139         if (!uwrap.enabled) {
140                 return getuid();
141         }
142         /* we don't simulate ruid changing */
143         return 0;
144 }
145
146 _PUBLIC_ gid_t uwrap_getgid(void)
147 {
148         uwrap_init();
149         if (!uwrap.enabled) {
150                 return getgid();
151         }
152         /* we don't simulate rgid changing */
153         return 0;
154 }