import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / sam / idmap_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    ID Mapping
4    Copyright (C) Simo Sorce 2003
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
19
20 #include "includes.h"
21
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_IDMAP
24
25 #if 0   /* NOT USED */
26
27 /**********************************************************************
28  Get the free RID base if idmap is configured, otherwise return 0
29 **********************************************************************/
30
31 uint32 idmap_get_free_rid_base(void)
32 {
33         uint32 low, high;
34         if (idmap_get_free_rid_range(&low, &high)) {
35                 return low;
36         }
37         return 0;
38 }
39
40 /**********************************************************************
41 **********************************************************************/
42
43 BOOL idmap_check_ugid_is_in_free_range(uint32 id)
44 {
45         uint32 low, high;
46
47         if (!idmap_get_free_ugid_range(&low, &high)) {
48                 return False;
49         }
50         if (id < low || id > high) {
51                 return False;
52         }
53         return True;
54 }
55
56 /**********************************************************************
57 **********************************************************************/
58
59 BOOL idmap_check_rid_is_in_free_range(uint32 rid)
60 {
61         uint32 low, high;
62
63         if (!idmap_get_free_rid_range(&low, &high)) {
64                 return False;
65         }
66         if (rid < algorithmic_rid_base()) {
67                 return True;
68         }
69
70         if (rid < low || rid > high) {
71                 return False;
72         }
73
74         return True;
75 }
76
77 /**********************************************************************
78  if it is a foreign SID or if the SID is in the free range, return true
79 **********************************************************************/
80
81 BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid)
82 {
83         if (sid_compare_domain(get_global_sam_sid(), sid) == 0) {
84         
85                 uint32 rid;
86
87                 if (sid_peek_rid(sid, &rid)) {
88                         return idmap_check_rid_is_in_free_range(rid);
89                 }
90
91                 return False;
92         }
93
94         return True;
95 }
96
97 #endif  /* NOT USED */
98
99 /*****************************************************************
100  Returns SID pointer.
101 *****************************************************************/  
102
103 NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid)
104 {
105         unid_t id;
106         int flags;
107
108         DEBUG(10,("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid));
109
110         flags = ID_USERID;
111         id.uid = uid;
112         
113         return idmap_get_sid_from_id(sid, id, flags);
114 }
115
116 /*****************************************************************
117  Group mapping is used for gids that maps to Wellknown SIDs
118  Returns SID pointer.
119 *****************************************************************/  
120
121 NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid)
122 {
123         unid_t id;
124         int flags;
125
126         DEBUG(10,("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid));
127
128         flags = ID_GROUPID;
129 #if 0   /* JERRY */
130         if (!idmap_check_ugid_is_in_free_range(gid)) {
131                 flags |= ID_QUERY_ONLY;
132         }
133 #endif
134         id.gid = gid;
135         return idmap_get_sid_from_id(sid, id, flags);
136 }
137
138 /*****************************************************************
139  if it is a foreign sid or it is in idmap rid range check idmap,
140  otherwise falls back to the legacy algorithmic mapping.
141  Returns True if this name is a user sid and the conversion
142  was done correctly, False if not.
143 *****************************************************************/  
144
145 NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags)
146 {
147         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
148         unid_t id;
149
150         DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
151
152         flags |= ID_USERID;
153
154         ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
155         
156         if ( NT_STATUS_IS_OK(ret) ) {
157                 DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid));
158                 *uid = id.uid;
159         } 
160
161         return ret;
162
163 }
164
165 /*****************************************************************
166  *THE CANONICAL* convert SID to gid function.
167  if it is a foreign sid or it is in idmap rid range check idmap,
168  otherwise falls back to the legacy algorithmic mapping.
169  Group mapping is used for gids that maps to Wellknown SIDs
170  Returns True if this name is a user sid and the conversion
171  was done correctly, False if not.
172 *****************************************************************/  
173
174 NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
175 {
176         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
177         unid_t id;
178
179         DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
180
181         flags |= ID_GROUPID;
182
183         ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
184         
185         if ( NT_STATUS_IS_OK(ret) ) 
186         {
187                 DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid));
188                 *gid = id.gid;
189         }
190
191         return ret;
192 }
193
194
195 /***************************************************************************
196  Check first, call set_mapping if it doesn't already exist.
197 ***************************************************************************/
198
199 static NTSTATUS wellknown_id_init(DOM_SID *sid, unid_t id, int flags)
200 {
201         unid_t storedid;
202         int qflags = flags | ID_QUERY_ONLY;
203
204         if (!NT_STATUS_IS_OK(idmap_get_id_from_sid(&storedid, &qflags, sid))) {
205                 return idmap_set_mapping(sid, id, flags);
206         } else {
207                 if (flags == ID_USERID && id.uid != storedid.uid) {
208                         DEBUG(0,("wellknown_id_init: WARNING ! Stored uid %u for SID %s is not the same as the requested uid %u\n",
209                                 (unsigned int)storedid.uid, sid_string_static(sid), (unsigned int)id.uid ));
210                         DEBUG(0,("wellknown_id_init: Attempting to overwrite old mapping with new.\n"));
211                         return idmap_set_mapping(sid, id, flags);
212                 } else if (flags == ID_GROUPID && id.gid != storedid.gid) {
213                         DEBUG(0,("wellknown_id_init: WARNING ! Stored gid %u for SID %s is not the same as the requested gid %u\n",
214                                 (unsigned int)storedid.gid, sid_string_static(sid), (unsigned int)id.gid ));
215                         DEBUG(0,("wellknown_id_init: Attempting to overwrite old mapping with new.\n"));
216                         return idmap_set_mapping(sid, id, flags);
217                 }
218         }
219         return NT_STATUS_OK;
220 }
221
222 /***************************************************************************
223  Initialize idmap withWellknown SIDs like Guest, that are necessary
224  to make samba run properly.
225 ***************************************************************************/
226
227 BOOL idmap_init_wellknown_sids(void)
228 {
229         const char *guest_account = lp_guestaccount();
230         struct passwd *pass;
231         GROUP_MAP *map=NULL;
232         int num_entries=0;
233         DOM_SID sid;
234         unid_t id;
235         fstring sid_string;
236
237         if (!(guest_account && *guest_account)) {
238                 DEBUG(1, ("NULL guest account!?!?\n"));
239                 return False;
240         }
241
242         pass = getpwnam_alloc(guest_account);
243         if (!pass) {
244                 return False;
245         }
246
247         /* Fill in the SID for the guest account. */
248         id.uid = pass->pw_uid;
249         sid_copy(&sid, get_global_sam_sid());
250         sid_append_rid(&sid, DOMAIN_USER_RID_GUEST);
251
252         if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) {
253                 DEBUG(0, ("Failed to setup UID mapping for GUEST (%s) to (%u)\n", 
254                           sid_to_string(sid_string, &sid), (unsigned int)id.uid));
255                 passwd_free(&pass);
256                 return False;
257         }
258
259         /* check if DOMAIN_GROUP_RID_GUESTS SID is set, if not store the
260          * guest account gid as mapping */
261         id.gid = pass->pw_gid;
262         sid_copy(&sid, get_global_sam_sid());
263         sid_append_rid(&sid, DOMAIN_GROUP_RID_GUESTS);
264         if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_GROUPID))) {
265                 DEBUG(0, ("Failed to setup GID mapping for Group DOMAIN GUESTS (%s) to (%u)\n", 
266                           sid_to_string(sid_string, &sid), (unsigned int)id.gid));
267                 passwd_free(&pass);
268                 return False;
269         }
270
271         passwd_free(&pass);
272         /* now fill in group mappings */
273         if(pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED)) {
274                 int i;
275
276                 for (i = 0; i < num_entries; i++) {
277                         id.gid = map[i].gid;
278                         wellknown_id_init(&map[i].sid, id, ID_GROUPID);
279                 }
280                 SAFE_FREE(map);
281         }
282
283         /* Fill in the SID for the administrator account. */
284         id.uid = 0;
285         sid_copy(&sid, get_global_sam_sid());
286         sid_append_rid(&sid, DOMAIN_USER_RID_ADMIN);
287
288         if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) {
289                 DEBUG(0, ("Failed to setup UID mapping for ADMINISTRATOR (%s) to (%u)\n", 
290                           sid_to_string(sid_string, &sid), (unsigned int)id.uid));
291                 return False;
292         }
293
294         return True;
295 }