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_proxyonly(void)
161 /**************************************************************************
162 This is a rare operation, designed to allow an explicit mapping to be
163 set up for a sid to a POSIX id.
164 **************************************************************************/
166 NTSTATUS
idmap_set_mapping(const DOM_SID
*sid
, unid_t id
, int id_type
)
168 struct idmap_methods
*map
= remote_map
;
172 return NT_STATUS_UNSUCCESSFUL
;
174 DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
175 sid_string_static(sid
),
176 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? "UID" : "GID",
177 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? (unsigned long)id
.uid
:
178 (unsigned long)id
.gid
));
180 if ( (NT_STATUS_IS_OK(cache_map
->
181 get_sid_from_id(&tmp_sid
, id
,
182 id_type
| ID_QUERY_ONLY
))) &&
183 sid_equal(sid
, &tmp_sid
) ) {
184 /* Nothing to do, we already have that mapping */
185 DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
190 /* Ok, we don't have a authoritative remote
191 mapping. So update our local cache only. */
195 return map
->set_mapping(sid
, id
, id_type
);
198 /**************************************************************************
199 Get ID from SID. This can create a mapping for a SID to a POSIX id.
200 **************************************************************************/
202 NTSTATUS
idmap_get_id_from_sid(unid_t
*id
, int *id_type
, const DOM_SID
*sid
)
209 return NT_STATUS_UNSUCCESSFUL
;
214 /* We have a central remote idmap so only look in
215 cache, don't allocate */
216 loc_type
|= ID_QUERY_ONLY
;
219 ret
= cache_map
->get_id_from_sid(id
, &loc_type
, sid
);
221 if (NT_STATUS_IS_OK(ret
)) {
222 *id_type
= loc_type
& ID_TYPEMASK
;
226 if (remote_map
== NULL
) {
230 /* Before forking out to the possibly slow remote map, lets see if we
231 * already have the sid as uid when asking for a gid or vice versa. */
233 loc_type
= *id_type
& ID_TYPEMASK
;
237 loc_type
= ID_GROUPID
;
240 loc_type
= ID_USERID
;
246 loc_type
|= ID_QUERY_ONLY
;
248 ret
= cache_map
->get_id_from_sid(&loc_id
, &loc_type
, sid
);
250 if (NT_STATUS_IS_OK(ret
)) {
251 /* Ok, we have the uid as gid or vice versa. The remote map
252 * would not know anything different, so return here. */
253 return NT_STATUS_UNSUCCESSFUL
;
256 /* Ok, the mapping was not in the cache, give the remote map a
259 ret
= remote_map
->get_id_from_sid(id
, id_type
, sid
);
261 if (NT_STATUS_IS_OK(ret
)) {
262 /* The remote backend gave us a valid mapping, cache it. */
263 ret
= cache_map
->set_mapping(sid
, *id
, *id_type
);
269 /**************************************************************************
270 Get SID from ID. This must have been created before.
271 **************************************************************************/
273 NTSTATUS
idmap_get_sid_from_id(DOM_SID
*sid
, unid_t id
, int id_type
)
279 return NT_STATUS_UNSUCCESSFUL
;
283 loc_type
= id_type
| ID_QUERY_ONLY
;
286 ret
= cache_map
->get_sid_from_id(sid
, id
, loc_type
);
288 if (NT_STATUS_IS_OK(ret
))
291 if (remote_map
== NULL
)
294 /* We have a second chance, ask our authoritative backend */
296 ret
= remote_map
->get_sid_from_id(sid
, id
, id_type
);
298 if (NT_STATUS_IS_OK(ret
)) {
299 /* The remote backend gave us a valid mapping, cache it. */
300 ret
= cache_map
->set_mapping(sid
, id
, id_type
);
306 /**************************************************************************
307 Alloocate a new UNIX uid/gid
308 **************************************************************************/
310 NTSTATUS
idmap_allocate_id(unid_t
*id
, int id_type
)
312 /* we have to allocate from the authoritative backend */
315 return NT_STATUS_UNSUCCESSFUL
;
318 return remote_map
->allocate_id( id
, id_type
);
320 return cache_map
->allocate_id( id
, id_type
);
323 /**************************************************************************
325 **************************************************************************/
327 NTSTATUS
idmap_allocate_rid(uint32
*rid
, int type
)
329 /* we have to allocate from the authoritative backend */
332 return NT_STATUS_UNSUCCESSFUL
;
335 return remote_map
->allocate_rid( rid
, type
);
337 return cache_map
->allocate_rid( rid
, type
);
340 /**************************************************************************
342 **************************************************************************/
344 NTSTATUS
idmap_close(void)
351 ret
= cache_map
->close();
352 if (!NT_STATUS_IS_OK(ret
)) {
353 DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
358 ret
= remote_map
->close();
359 if (!NT_STATUS_IS_OK(ret
)) {
360 DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
368 /**************************************************************************
370 **************************************************************************/
372 void idmap_status(void)
376 remote_map
->status();