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 /**********************************************************************
40 Get idmap methods. Don't allow tdb to be a remote method.
41 **********************************************************************/
43 static struct idmap_methods
*get_methods(const char *name
, BOOL cache_method
)
45 struct idmap_function_entry
*entry
= backends
;
47 for(entry
= backends
; entry
; entry
= entry
->next
) {
48 if (!cache_method
&& strequal(entry
->name
, "tdb"))
49 continue; /* tdb is only cache method. */
50 if (strequal(entry
->name
, name
))
51 return entry
->methods
;
57 /**********************************************************************
58 Allow a module to register itself as a method.
59 **********************************************************************/
61 NTSTATUS
smb_register_idmap(int version
, const char *name
, struct idmap_methods
*methods
)
63 struct idmap_function_entry
*entry
;
65 if ((version
!= SMB_IDMAP_INTERFACE_VERSION
)) {
66 DEBUG(0, ("smb_register_idmap: Failed to register idmap module.\n"
67 "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n"
68 "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
69 "Please recompile against the current version of samba!\n",
70 version
, SMB_IDMAP_INTERFACE_VERSION
));
71 return NT_STATUS_OBJECT_TYPE_MISMATCH
;
74 if (!name
|| !name
[0] || !methods
) {
75 DEBUG(0,("smb_register_idmap: called with NULL pointer or empty name!\n"));
76 return NT_STATUS_INVALID_PARAMETER
;
79 if (get_methods(name
, False
)) {
80 DEBUG(0,("smb_register_idmap: idmap module %s already registered!\n", name
));
81 return NT_STATUS_OBJECT_NAME_COLLISION
;
84 entry
= smb_xmalloc(sizeof(struct idmap_function_entry
));
85 entry
->name
= smb_xstrdup(name
);
86 entry
->methods
= methods
;
88 DLIST_ADD(backends
, entry
);
89 DEBUG(5, ("smb_register_idmap: Successfully added idmap backend '%s'\n", name
));
93 /**********************************************************************
94 Initialise idmap cache and a remote backend (if configured).
95 **********************************************************************/
97 BOOL
idmap_init(const char *remote_backend
)
103 cache_map
= get_methods("tdb", True
);
106 DEBUG(0, ("idmap_init: could not find tdb cache backend!\n"));
110 if (!NT_STATUS_IS_OK(cache_map
->init( NULL
))) {
111 DEBUG(0, ("idmap_init: could not initialise tdb cache backend!\n"));
116 if (!remote_map
&& remote_backend
&& *remote_backend
!= 0) {
117 char *rem_backend
= smb_xstrdup(remote_backend
);
121 /* get any mode parameters passed in */
123 if ( (pparams
= strchr( rem_backend
, ':' )) != NULL
) {
126 fstrcpy( params
, pparams
);
129 DEBUG(3, ("idmap_init: using '%s' as remote backend\n", rem_backend
));
131 if((remote_map
= get_methods(rem_backend
, False
)) ||
132 (NT_STATUS_IS_OK(smb_probe_module("idmap", rem_backend
)) &&
133 (remote_map
= get_methods(rem_backend
, False
)))) {
134 remote_map
->init(params
);
136 DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", rem_backend
));
137 SAFE_FREE(rem_backend
);
140 SAFE_FREE(rem_backend
);
146 /**************************************************************************
147 This is a rare operation, designed to allow an explicit mapping to be
148 set up for a sid to a POSIX id.
149 **************************************************************************/
151 NTSTATUS
idmap_set_mapping(const DOM_SID
*sid
, unid_t id
, int id_type
)
153 struct idmap_methods
*map
= remote_map
;
156 DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
157 sid_string_static(sid
),
158 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? "UID" : "GID",
159 ((id_type
& ID_TYPEMASK
) == ID_USERID
) ? (unsigned long)id
.uid
:
160 (unsigned long)id
.gid
));
162 if ( (NT_STATUS_IS_OK(cache_map
->
163 get_sid_from_id(&tmp_sid
, id
,
164 id_type
| ID_QUERY_ONLY
))) &&
165 sid_equal(sid
, &tmp_sid
) ) {
166 /* Nothing to do, we already have that mapping */
167 DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
172 /* Ok, we don't have a authoritative remote
173 mapping. So update our local cache only. */
177 return map
->set_mapping(sid
, id
, id_type
);
180 /**************************************************************************
181 Get ID from SID. This can create a mapping for a SID to a POSIX id.
182 **************************************************************************/
184 NTSTATUS
idmap_get_id_from_sid(unid_t
*id
, int *id_type
, const DOM_SID
*sid
)
192 /* We have a central remote idmap so only look in
193 cache, don't allocate */
194 loc_type
|= ID_QUERY_ONLY
;
197 ret
= cache_map
->get_id_from_sid(id
, &loc_type
, sid
);
199 if (NT_STATUS_IS_OK(ret
)) {
200 *id_type
= loc_type
& ID_TYPEMASK
;
204 if (remote_map
== NULL
) {
208 /* Ok, the mapping was not in the cache, give the remote map a
211 ret
= remote_map
->get_id_from_sid(id
, id_type
, sid
);
213 if (NT_STATUS_IS_OK(ret
)) {
214 /* The remote backend gave us a valid mapping, cache it. */
215 ret
= cache_map
->set_mapping(sid
, *id
, *id_type
);
221 /**************************************************************************
222 Get SID from ID. This must have been created before.
223 **************************************************************************/
225 NTSTATUS
idmap_get_sid_from_id(DOM_SID
*sid
, unid_t id
, int id_type
)
232 loc_type
= id_type
| ID_QUERY_ONLY
;
235 ret
= cache_map
->get_sid_from_id(sid
, id
, loc_type
);
237 if (NT_STATUS_IS_OK(ret
))
240 if (remote_map
== NULL
)
243 /* We have a second chance, ask our authoritative backend */
245 ret
= remote_map
->get_sid_from_id(sid
, id
, id_type
);
247 if (NT_STATUS_IS_OK(ret
)) {
248 /* The remote backend gave us a valid mapping, cache it. */
249 ret
= cache_map
->set_mapping(sid
, id
, id_type
);
255 /**************************************************************************
256 Alloocate a new UNIX uid/gid
257 **************************************************************************/
259 NTSTATUS
idmap_allocate_id(unid_t
*id
, int id_type
)
261 /* we have to allocate from the authoritative backend */
264 return remote_map
->allocate_id( id
, id_type
);
266 return cache_map
->allocate_id( id
, id_type
);
269 /**************************************************************************
271 **************************************************************************/
273 NTSTATUS
idmap_allocate_rid(uint32
*rid
, int type
)
275 /* we have to allocate from the authoritative backend */
278 return remote_map
->allocate_rid( rid
, type
);
280 return cache_map
->allocate_rid( rid
, type
);
283 /**************************************************************************
285 **************************************************************************/
287 NTSTATUS
idmap_close(void)
291 ret
= cache_map
->close();
292 if (!NT_STATUS_IS_OK(ret
)) {
293 DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
298 ret
= remote_map
->close();
299 if (!NT_STATUS_IS_OK(ret
)) {
300 DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
308 /**************************************************************************
310 **************************************************************************/
312 void idmap_status(void)
316 remote_map
->status();