e009fa0b5c3eedf607e68df962e0e6b874b26c32
[sfrench/samba-autobuild/.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 _PUBLIC_ int uwrap_seteuid(uid_t euid)
49 {
50         uwrap_init();
51         if (!uwrap.enabled) {
52                 return seteuid(euid);
53         }
54         /* assume for now that the ruid stays as root */
55         uwrap.euid = euid;
56         return 0;
57 }
58
59 _PUBLIC_ uid_t uwrap_geteuid(void)
60 {
61         uwrap_init();
62         if (!uwrap.enabled) {
63                 return geteuid();
64         }
65         return uwrap.euid;
66 }
67
68 _PUBLIC_ int uwrap_setegid(gid_t egid)
69 {
70         uwrap_init();
71         if (!uwrap.enabled) {
72                 return setegid(egid);
73         }
74         /* assume for now that the ruid stays as root */
75         uwrap.egid = egid;
76         return 0;
77 }
78
79 _PUBLIC_ uid_t uwrap_getegid(void)
80 {
81         uwrap_init();
82         if (!uwrap.enabled) {
83                 return getegid();
84         }
85         return uwrap.egid;
86 }
87
88 _PUBLIC_ int uwrap_setgroups(size_t size, const gid_t *list)
89 {
90         uwrap_init();
91         if (!uwrap.enabled) {
92                 return setgroups(size, list);
93         }
94
95         talloc_free(uwrap.groups);
96         uwrap.ngroups = 0;
97
98         uwrap.groups = talloc_array(talloc_autofree_context(), gid_t, size);
99         if (uwrap.groups == NULL) {
100                 errno = ENOMEM;
101                 return -1;
102         }
103         memcpy(uwrap.groups, list, size*sizeof(gid_t));
104         uwrap.ngroups = size;
105         return 0;
106 }
107
108 _PUBLIC_ int uwrap_getgroups(int size, gid_t *list)
109 {
110         uwrap_init();
111         if (!uwrap.enabled) {
112                 return getgroups(size, list);
113         }
114
115         if (size > uwrap.ngroups) {
116                 size = uwrap.ngroups;
117         }
118         if (size == 0) {
119                 return uwrap.ngroups;
120         }
121         if (size < uwrap.ngroups) {
122                 errno = EINVAL;
123                 return -1;
124         }
125         memcpy(list, uwrap.groups, size*sizeof(gid_t));
126         return 0;
127 }
128
129 _PUBLIC_ uid_t uwrap_getuid(void)
130 {
131         uwrap_init();
132         if (!uwrap.enabled) {
133                 return getuid();
134         }
135         /* we don't simulate ruid changing */
136         return 0;
137 }
138
139 _PUBLIC_ gid_t uwrap_getgid(void)
140 {
141         uwrap_init();
142         if (!uwrap.enabled) {
143                 return getgid();
144         }
145         /* we don't simulate rgid changing */
146         return 0;
147 }