2 Unix SMB/CIFS implementation.
4 Copyright (C) Tim Potter 2000
5 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
6 Copyright (C) Simo Sorce 2003
7 Copyright (C) Jeremy Allison 2003.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
26 #define DBGC_CLASS DBGC_IDMAP
28 struct idmap_function_entry
{
30 struct idmap_methods
*methods
;
31 struct idmap_function_entry
*prev
,*next
;
34 static struct idmap_function_entry
*backends
= NULL
;
36 static struct idmap_methods
*cache_map
;
37 static struct idmap_methods
*remote_map
;
39 static BOOL proxyonly
= False
;
41 /**********************************************************************
42 Get idmap methods. Don't allow tdb to be a remote method.
43 **********************************************************************/
45 static struct idmap_methods
*get_methods(const char *name
, BOOL cache_method
)
47 struct idmap_function_entry
*entry
= backends
;
49 for(entry
= backends
; entry
; entry
= entry
->next
) {
50 if (!cache_method
&& strequal(entry
->name
, "tdb"))
51 continue; /* tdb is only cache method. */
52 if (strequal(entry
->name
, name
))
53 return entry
->methods
;
59 /**********************************************************************
60 Allow a module to register itself as a method.
61 **********************************************************************/
63 NTSTATUS
smb_register_idmap(int version
, const char *name
, struct idmap_methods
*methods
)
65 struct idmap_function_entry
*entry
;
67 if ((version
!= SMB_IDMAP_INTERFACE_VERSION
)) {
68 DEBUG(0, ("smb_register_idmap: Failed to register idmap module.\n"
69 "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n"
70 "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
71 "Please recompile against the current version of samba!\n",
72 version
, SMB_IDMAP_INTERFACE_VERSION
));
73 return NT_STATUS_OBJECT_TYPE_MISMATCH
;
76 if (!name
|| !name
[0] || !methods
) {
77 DEBUG(0,("smb_register_idmap: called with NULL pointer or empty name!\n"));
78 return NT_STATUS_INVALID_PARAMETER
;
81 if (get_methods(name
, False
)) {
82 DEBUG(0,("smb_register_idmap: idmap module %s already registered!\n", name
));
83 return NT_STATUS_OBJECT_NAME_COLLISION
;
86 entry
= SMB_XMALLOC_P(struct idmap_function_entry
);
87 entry
->name
= smb_xstrdup(name
);
88 entry
->methods
= methods
;
90 DLIST_ADD(backends
, entry
);
91 DEBUG(5, ("smb_register_idmap: Successfully added idmap backend '%s'\n", name
));
95 /**********************************************************************
96 Initialise idmap cache and a remote backend (if configured).
97 **********************************************************************/
99 BOOL
idmap_init(const char **remote_backend
)
105 cache_map
= get_methods("tdb", True
);
108 DEBUG(0, ("idmap_init: could not find tdb cache backend!\n"));
112 if (!NT_STATUS_IS_OK(cache_map
->init( NULL
))) {
113 DEBUG(0, ("idmap_init: could not initialise tdb cache backend!\n"));
118 if ((remote_map
== NULL
) && (remote_backend
!= NULL
) &&
119 (*remote_backend
!= NULL
) && (**remote_backend
!= '\0')) {
120 char *rem_backend
= smb_xstrdup(*remote_backend
);
124 /* get any mode parameters passed in */
126 if ( (pparams
= strchr( rem_backend
, ':' )) != NULL
) {
129 fstrcpy( params
, pparams
);
132 DEBUG(3, ("idmap_init: using '%s' as remote backend\n", rem_backend
));
134 if((remote_map
= get_methods(rem_backend
, False
)) ||
135 (NT_STATUS_IS_OK(smb_probe_module("idmap", rem_backend
)) &&
136 (remote_map
= get_methods(rem_backend
, False
)))) {
137 if (!NT_STATUS_IS_OK(remote_map
->init(params
))) {
138 DEBUG(0, ("idmap_init: failed to initialize remote backend!\n"));
142 DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", rem_backend
));
143 SAFE_FREE(rem_backend
);
146 SAFE_FREE(rem_backend
);
152 /**************************************************************************
153 Don't do id mapping. This is used to make winbind a netlogon proxy only.
154 **************************************************************************/
156 void idmap_set_proxyonly(void)
161 BOOL
idmap_proxyonly(void)
166 /**************************************************************************
167 This is a rare operation, designed to allow an explicit mapping to be
168 set up for a sid to a POSIX id.
169 **************************************************************************/
171 NTSTATUS
idmap_set_mapping(const DOM_SID
*sid
, unid_t id
, int id_type
)
173 struct idmap_methods
*map
= remote_map
;
177 return NT_STATUS_UNSUCCESSFUL
;
179 DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
180 sid_string_static(sid
),
181 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? "UID" : "GID",
182 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? (unsigned long)id
.uid
:
183 (unsigned long)id
.gid
));
185 if ( (NT_STATUS_IS_OK(cache_map
->
186 get_sid_from_id(&tmp_sid
, id
,
187 id_type
| ID_QUERY_ONLY
))) &&
188 sid_equal(sid
, &tmp_sid
) ) {
189 /* Nothing to do, we already have that mapping */
190 DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
195 /* Ok, we don't have a authoritative remote
196 mapping. So update our local cache only. */
200 return map
->set_mapping(sid
, id
, id_type
);
203 /**************************************************************************
204 Get ID from SID. This can create a mapping for a SID to a POSIX id.
205 **************************************************************************/
207 NTSTATUS
idmap_get_id_from_sid(unid_t
*id
, int *id_type
, const DOM_SID
*sid
)
214 return NT_STATUS_UNSUCCESSFUL
;
219 /* We have a central remote idmap so only look in
220 cache, don't allocate */
221 loc_type
|= ID_QUERY_ONLY
;
224 ret
= cache_map
->get_id_from_sid(id
, &loc_type
, sid
);
226 if (NT_STATUS_IS_OK(ret
)) {
227 *id_type
= loc_type
& ID_TYPEMASK
;
231 if ((remote_map
== NULL
) || (loc_type
& ID_CACHE_ONLY
)) {
235 /* Before forking out to the possibly slow remote map, lets see if we
236 * already have the sid as uid when asking for a gid or vice versa. */
238 loc_type
= *id_type
& ID_TYPEMASK
;
242 loc_type
= ID_GROUPID
;
245 loc_type
= ID_USERID
;
251 loc_type
|= ID_QUERY_ONLY
;
253 ret
= cache_map
->get_id_from_sid(&loc_id
, &loc_type
, sid
);
255 if (NT_STATUS_IS_OK(ret
)) {
256 /* Ok, we have the uid as gid or vice versa. The remote map
257 * would not know anything different, so return here. */
258 return NT_STATUS_UNSUCCESSFUL
;
261 /* Ok, the mapping was not in the cache, give the remote map a
264 ret
= remote_map
->get_id_from_sid(id
, id_type
, sid
);
266 if (NT_STATUS_IS_OK(ret
)) {
267 /* The remote backend gave us a valid mapping, cache it. */
268 ret
= cache_map
->set_mapping(sid
, *id
, *id_type
);
274 /**************************************************************************
275 Get SID from ID. This must have been created before.
276 **************************************************************************/
278 NTSTATUS
idmap_get_sid_from_id(DOM_SID
*sid
, unid_t id
, int id_type
)
284 return NT_STATUS_UNSUCCESSFUL
;
288 loc_type
= id_type
| ID_QUERY_ONLY
;
291 ret
= cache_map
->get_sid_from_id(sid
, id
, loc_type
);
293 if (NT_STATUS_IS_OK(ret
))
296 if ((remote_map
== NULL
) || (loc_type
& ID_CACHE_ONLY
))
299 /* We have a second chance, ask our authoritative backend */
301 ret
= remote_map
->get_sid_from_id(sid
, id
, id_type
);
303 if (NT_STATUS_IS_OK(ret
)) {
304 /* The remote backend gave us a valid mapping, cache it. */
305 ret
= cache_map
->set_mapping(sid
, id
, id_type
);
311 /**************************************************************************
312 Alloocate a new UNIX uid/gid
313 **************************************************************************/
315 NTSTATUS
idmap_allocate_id(unid_t
*id
, int id_type
)
317 /* we have to allocate from the authoritative backend */
320 return NT_STATUS_UNSUCCESSFUL
;
323 return remote_map
->allocate_id( id
, id_type
);
325 return cache_map
->allocate_id( id
, id_type
);
328 /**************************************************************************
330 **************************************************************************/
332 NTSTATUS
idmap_allocate_rid(uint32
*rid
, int type
)
334 /* we have to allocate from the authoritative backend */
337 return NT_STATUS_UNSUCCESSFUL
;
340 return remote_map
->allocate_rid( rid
, type
);
342 return cache_map
->allocate_rid( rid
, type
);
345 /**************************************************************************
347 **************************************************************************/
349 NTSTATUS
idmap_close(void)
356 ret
= cache_map
->close_fn();
357 if (!NT_STATUS_IS_OK(ret
)) {
358 DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
363 ret
= remote_map
->close_fn();
364 if (!NT_STATUS_IS_OK(ret
)) {
365 DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
373 /**************************************************************************
375 **************************************************************************/
377 void idmap_status(void)
381 remote_map
->status();