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(sizeof(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 remote_map
->init(params
);
139 DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", rem_backend
));
140 SAFE_FREE(rem_backend
);
143 SAFE_FREE(rem_backend
);
149 /**************************************************************************
150 Don't do id mapping. This is used to make winbind a netlogon proxy only.
151 **************************************************************************/
153 void idmap_proxyonly(void)
158 /**************************************************************************
159 This is a rare operation, designed to allow an explicit mapping to be
160 set up for a sid to a POSIX id.
161 **************************************************************************/
163 NTSTATUS
idmap_set_mapping(const DOM_SID
*sid
, unid_t id
, int id_type
)
165 struct idmap_methods
*map
= remote_map
;
169 return NT_STATUS_UNSUCCESSFUL
;
171 DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
172 sid_string_static(sid
),
173 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? "UID" : "GID",
174 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? (unsigned long)id
.uid
:
175 (unsigned long)id
.gid
));
177 if ( (NT_STATUS_IS_OK(cache_map
->
178 get_sid_from_id(&tmp_sid
, id
,
179 id_type
| ID_QUERY_ONLY
))) &&
180 sid_equal(sid
, &tmp_sid
) ) {
181 /* Nothing to do, we already have that mapping */
182 DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
187 /* Ok, we don't have a authoritative remote
188 mapping. So update our local cache only. */
192 return map
->set_mapping(sid
, id
, id_type
);
195 /**************************************************************************
196 Get ID from SID. This can create a mapping for a SID to a POSIX id.
197 **************************************************************************/
199 NTSTATUS
idmap_get_id_from_sid(unid_t
*id
, int *id_type
, const DOM_SID
*sid
)
205 return NT_STATUS_UNSUCCESSFUL
;
210 /* We have a central remote idmap so only look in
211 cache, don't allocate */
212 loc_type
|= ID_QUERY_ONLY
;
215 ret
= cache_map
->get_id_from_sid(id
, &loc_type
, sid
);
217 if (NT_STATUS_IS_OK(ret
)) {
218 *id_type
= loc_type
& ID_TYPEMASK
;
222 if (remote_map
== NULL
) {
226 /* Ok, the mapping was not in the cache, give the remote map a
229 ret
= remote_map
->get_id_from_sid(id
, id_type
, sid
);
231 if (NT_STATUS_IS_OK(ret
)) {
232 /* The remote backend gave us a valid mapping, cache it. */
233 ret
= cache_map
->set_mapping(sid
, *id
, *id_type
);
239 /**************************************************************************
240 Get SID from ID. This must have been created before.
241 **************************************************************************/
243 NTSTATUS
idmap_get_sid_from_id(DOM_SID
*sid
, unid_t id
, int id_type
)
249 return NT_STATUS_UNSUCCESSFUL
;
253 loc_type
= id_type
| ID_QUERY_ONLY
;
256 ret
= cache_map
->get_sid_from_id(sid
, id
, loc_type
);
258 if (NT_STATUS_IS_OK(ret
))
261 if (remote_map
== NULL
)
264 /* We have a second chance, ask our authoritative backend */
266 ret
= remote_map
->get_sid_from_id(sid
, id
, id_type
);
268 if (NT_STATUS_IS_OK(ret
)) {
269 /* The remote backend gave us a valid mapping, cache it. */
270 ret
= cache_map
->set_mapping(sid
, id
, id_type
);
276 /**************************************************************************
277 Alloocate a new UNIX uid/gid
278 **************************************************************************/
280 NTSTATUS
idmap_allocate_id(unid_t
*id
, int id_type
)
282 /* we have to allocate from the authoritative backend */
285 return NT_STATUS_UNSUCCESSFUL
;
288 return remote_map
->allocate_id( id
, id_type
);
290 return cache_map
->allocate_id( id
, id_type
);
293 /**************************************************************************
295 **************************************************************************/
297 NTSTATUS
idmap_allocate_rid(uint32
*rid
, int type
)
299 /* we have to allocate from the authoritative backend */
302 return NT_STATUS_UNSUCCESSFUL
;
305 return remote_map
->allocate_rid( rid
, type
);
307 return cache_map
->allocate_rid( rid
, type
);
310 /**************************************************************************
312 **************************************************************************/
314 NTSTATUS
idmap_close(void)
321 ret
= cache_map
->close();
322 if (!NT_STATUS_IS_OK(ret
)) {
323 DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
328 ret
= remote_map
->close();
329 if (!NT_STATUS_IS_OK(ret
)) {
330 DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
338 /**************************************************************************
340 **************************************************************************/
342 void idmap_status(void)
346 remote_map
->status();