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