Merge branch 'v3-devel' of ssh://git.samba.org/data/git/samba into v3-devel
[ira/wip.git] / source3 / winbindd / idmap_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    ID Mapping
4    Copyright (C) Simo Sorce 2003
5    Copyright (C) Jeremy Allison 2006
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
19
20 #include "includes.h"
21
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_IDMAP
24
25 /*****************************************************************
26  Returns the SID mapped to the given UID.
27  If mapping is not possible returns an error.
28 *****************************************************************/  
29
30 NTSTATUS idmap_uid_to_sid(const char *domname, DOM_SID *sid, uid_t uid)
31 {
32         NTSTATUS ret;
33         struct id_map map;
34         bool expired;
35
36         DEBUG(10,("uid = [%lu]\n", (unsigned long)uid));
37
38         if (idmap_cache_find_uid2sid(uid, sid, &expired)) {
39                 DEBUG(10, ("idmap_cache_find_uid2sid found %d%s\n", uid,
40                            expired ? " (expired)": ""));
41                 if (expired && idmap_is_online()) {
42                         DEBUG(10, ("revalidating expired entry\n"));
43                         goto backend;
44                 }
45                 if (is_null_sid(sid)) {
46                         DEBUG(10, ("Returning negative cache entry\n"));
47                         return NT_STATUS_NONE_MAPPED;
48                 }
49                 DEBUG(10, ("Returning positive cache entry\n"));
50                 return NT_STATUS_OK;
51         }
52
53 backend:
54         map.sid = sid;
55         map.xid.type = ID_TYPE_UID;
56         map.xid.id = uid;
57
58         ret = idmap_backends_unixid_to_sid(domname, &map);
59         if ( ! NT_STATUS_IS_OK(ret)) {
60                 DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid));
61                 return ret;
62         }
63
64         if (map.status != ID_MAPPED) {
65                 struct dom_sid null_sid;
66                 ZERO_STRUCT(null_sid);
67                 idmap_cache_set_sid2uid(&null_sid, uid);
68                 DEBUG(10, ("uid [%lu] not mapped\n", (unsigned long)uid));
69                 return NT_STATUS_NONE_MAPPED;
70         }
71
72         idmap_cache_set_sid2uid(sid, uid);
73
74         return NT_STATUS_OK;
75 }
76
77 /*****************************************************************
78  Returns SID mapped to the given GID.
79  If mapping is not possible returns an error.
80 *****************************************************************/  
81
82 NTSTATUS idmap_gid_to_sid(const char *domname, DOM_SID *sid, gid_t gid)
83 {
84         NTSTATUS ret;
85         struct id_map map;
86         bool expired;
87
88         DEBUG(10,("gid = [%lu]\n", (unsigned long)gid));
89
90         if (idmap_cache_find_gid2sid(gid, sid, &expired)) {
91                 DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n", gid,
92                            expired ? " (expired)": ""));
93                 if (expired && idmap_is_online()) {
94                         DEBUG(10, ("revalidating expired entry\n"));
95                         goto backend;
96                 }
97                 if (is_null_sid(sid)) {
98                         DEBUG(10, ("Returning negative cache entry\n"));
99                         return NT_STATUS_NONE_MAPPED;
100                 }
101                 DEBUG(10, ("Returning positive cache entry\n"));
102                 return NT_STATUS_OK;
103         }
104
105 backend:
106         map.sid = sid;
107         map.xid.type = ID_TYPE_GID;
108         map.xid.id = gid;
109
110         ret = idmap_backends_unixid_to_sid(domname, &map);
111         if ( ! NT_STATUS_IS_OK(ret)) {
112                 DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid));
113                 return ret;
114         }
115
116         if (map.status != ID_MAPPED) {
117                 struct dom_sid null_sid;
118                 ZERO_STRUCT(null_sid);
119                 idmap_cache_set_sid2uid(&null_sid, gid);
120                 DEBUG(10, ("gid [%lu] not mapped\n", (unsigned long)gid));
121                 return NT_STATUS_NONE_MAPPED;
122         }
123
124         idmap_cache_set_sid2uid(sid, gid);
125
126         return NT_STATUS_OK;
127 }
128
129 /*****************************************************************
130  Returns the UID mapped to the given SID.
131  If mapping is not possible or SID maps to a GID returns an error.
132 *****************************************************************/  
133
134 NTSTATUS idmap_sid_to_uid(const char *dom_name, DOM_SID *sid, uid_t *uid)
135 {
136         NTSTATUS ret;
137         struct id_map map;
138         bool expired;
139
140         DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_dbg(sid)));
141
142         if (idmap_cache_find_sid2uid(sid, uid, &expired)) {
143                 DEBUG(10, ("idmap_cache_find_sid2uid found %d%s\n",
144                            (int)(*uid), expired ? " (expired)": ""));
145                 if (expired && idmap_is_online()) {
146                         DEBUG(10, ("revalidating expired entry\n"));
147                         goto backend;
148                 }
149                 if ((*uid) == -1) {
150                         DEBUG(10, ("Returning negative cache entry\n"));
151                         return NT_STATUS_NONE_MAPPED;
152                 }
153                 DEBUG(10, ("Returning positive cache entry\n"));
154                 return NT_STATUS_OK;
155         }
156
157 backend:
158         map.sid = sid;
159         map.xid.type = ID_TYPE_UID;     
160
161         ret = idmap_backends_sid_to_unixid(dom_name, &map);
162
163         if (NT_STATUS_IS_OK(ret) && (map.status == ID_MAPPED)) {
164                 if (map.xid.type != ID_TYPE_UID) {
165                         DEBUG(10, ("sid [%s] not mapped to a uid "
166                                    "[%u,%u,%u]\n",
167                                    sid_string_dbg(sid),
168                                    map.status,
169                                    map.xid.type,
170                                    map.xid.id));
171                         idmap_cache_set_sid2uid(sid, -1);
172                         return NT_STATUS_NONE_MAPPED;
173                 }
174                 goto done;
175         }
176
177         if (dom_name[0] != '\0') {
178                 /*
179                  * We had the task to go to a specific domain which
180                  * could not answer our request. Fail.
181                  */
182                 idmap_cache_set_sid2uid(sid, -1);
183                 return NT_STATUS_NONE_MAPPED;
184         }
185
186         ret = idmap_new_mapping(sid, ID_TYPE_UID, &map.xid);
187
188         if (!NT_STATUS_IS_OK(ret)) {
189                 DEBUG(10, ("idmap_new_mapping failed: %s\n",
190                            nt_errstr(ret)));
191                 idmap_cache_set_sid2uid(sid, -1);
192                 return ret;
193         }
194
195 done:
196         *uid = (uid_t)map.xid.id;
197         idmap_cache_set_sid2uid(sid, *uid);
198         return NT_STATUS_OK;
199 }
200
201 /*****************************************************************
202  Returns the GID mapped to the given SID.
203  If mapping is not possible or SID maps to a UID returns an error.
204 *****************************************************************/  
205
206 NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid)
207 {
208         NTSTATUS ret;
209         struct id_map map;
210         bool expired;
211
212         DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_dbg(sid)));
213
214         if (idmap_cache_find_sid2gid(sid, gid, &expired)) {
215                 DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n",
216                            (int)(*gid), expired ? " (expired)": ""));
217                 if (expired && idmap_is_online()) {
218                         DEBUG(10, ("revalidating expired entry\n"));
219                         goto backend;
220                 }
221                 if ((*gid) == -1) {
222                         DEBUG(10, ("Returning negative cache entry\n"));
223                         return NT_STATUS_NONE_MAPPED;
224                 }
225                 DEBUG(10, ("Returning positive cache entry\n"));
226                 return NT_STATUS_OK;
227         }
228
229 backend:
230         map.sid = sid;
231         map.xid.type = ID_TYPE_GID;
232
233         ret = idmap_backends_sid_to_unixid(domname, &map);
234         if (NT_STATUS_IS_OK(ret) && (map.status == ID_MAPPED)) {
235                 if (map.xid.type != ID_TYPE_GID) {
236                         DEBUG(10, ("sid [%s] not mapped to a gid "
237                                    "[%u,%u,%u]\n",
238                                    sid_string_dbg(sid),
239                                    map.status,
240                                    map.xid.type,
241                                    map.xid.id));
242                         idmap_cache_set_sid2gid(sid, -1);
243                         return NT_STATUS_NONE_MAPPED;
244                 }
245                 goto done;
246         }
247
248         if (domname[0] != '\0') {
249                 /*
250                  * We had the task to go to a specific domain which
251                  * could not answer our request. Fail.
252                  */
253                 idmap_cache_set_sid2uid(sid, -1);
254                 return NT_STATUS_NONE_MAPPED;
255         }
256
257         ret = idmap_new_mapping(sid, ID_TYPE_GID, &map.xid);
258
259         if (!NT_STATUS_IS_OK(ret)) {
260                 DEBUG(10, ("idmap_new_mapping failed: %s\n",
261                            nt_errstr(ret)));
262                 idmap_cache_set_sid2gid(sid, -1);
263                 return ret;
264         }
265
266 done:
267         *gid = map.xid.id;
268         idmap_cache_set_sid2gid(sid, *gid);
269         return NT_STATUS_OK;
270 }