2 * idmap_adex: Support for D Forests
4 * Copyright (C) Gerald (Jerry) Carter 2006-2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "idmap_adex.h"
29 #define DBGC_CLASS DBGC_IDMAP
31 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
37 /********************************************************************
38 Basic init function responsible for determining our current mode
39 (standalone or using Centeris Cells). This must return success or
40 it will be dropped from the idmap backend list.
41 *******************************************************************/
43 static NTSTATUS
_idmap_adex_init(struct idmap_domain
*dom
)
45 ADS_STRUCT
*ads
= NULL
;
47 static NTSTATUS init_status
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
48 struct dom_sid domain_sid
;
50 struct sockaddr_storage ip
;
51 struct likewise_cell
*lwcell
;
53 if (NT_STATUS_IS_OK(init_status
))
56 /* Silently fail if we are not a member server in security = ads */
58 if ((lp_server_role() != ROLE_DOMAIN_MEMBER
) ||
59 (lp_security() != SEC_ADS
)) {
60 init_status
= NT_STATUS_INVALID_SERVER_STATE
;
61 BAIL_ON_NTSTATUS_ERROR(init_status
);
64 /* fetch our domain SID first */
66 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
67 init_status
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
68 BAIL_ON_NTSTATUS_ERROR(init_status
);
71 /* reuse the same ticket cache as winbindd */
73 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME
, 1);
75 /* Establish a connection to a DC */
77 if ((ads
= ads_init(lp_realm(), lp_workgroup(), NULL
)) == NULL
) {
78 init_status
= NT_STATUS_NO_MEMORY
;
79 BAIL_ON_NTSTATUS_ERROR(init_status
);
83 secrets_fetch_machine_password(lp_workgroup(), NULL
, NULL
);
84 ads
->auth
.realm
= SMB_STRDUP(lp_realm());
86 /* get the DC name here to setup the server affinity cache and
89 get_dc_name(lp_workgroup(), lp_realm(), dcname
, &ip
);
91 status
= ads_connect(ads
);
92 if (!ADS_ERR_OK(status
)) {
93 DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
96 init_status
= ads_ntstatus(status
);
97 BAIL_ON_NTSTATUS_ERROR(init_status
);
100 /* Find out cell membership */
102 init_status
= cell_locate_membership(ads
);
103 if (!NT_STATUS_IS_OK(init_status
)) {
104 DEBUG(0,("LWI: Fail to locate cell membership (%s).",
105 nt_errstr(init_status
)));
109 /* Fill in the cell information */
111 lwcell
= cell_list_head();
113 init_status
= cell_lookup_settings(lwcell
);
114 BAIL_ON_NTSTATUS_ERROR(init_status
);
116 /* Miscellaneous setup. E.g. set up the list of GC
117 servers and domain list for our forest (does not actually
120 init_status
= gc_init_list();
121 BAIL_ON_NTSTATUS_ERROR(init_status
);
123 init_status
= domain_init_list();
124 BAIL_ON_NTSTATUS_ERROR(init_status
);
127 if (!NT_STATUS_IS_OK(init_status
)) {
128 DEBUG(1,("Likewise initialization failed (%s)\n",
129 nt_errstr(init_status
)));
134 if (!NT_STATUS_IS_OK(init_status
)) {
137 /* init_status stores the failure reason but we need to
138 return success or else idmap_init() will drop us from the
143 init_status
= NT_STATUS_OK
;
148 /**********************************************************************
149 *********************************************************************/
151 static NTSTATUS
_idmap_adex_get_sid_from_id(struct
158 bool one_mapped
= false;
159 bool all_mapped
= true;
161 struct likewise_cell
*cell
;
163 /* initialize the status to avoid suprise */
164 for (i
= 0; ids
[i
]; i
++) {
165 ids
[i
]->status
= ID_UNKNOWN
;
168 nt_status
= _idmap_adex_init(dom
);
169 if (!NT_STATUS_IS_OK(nt_status
))
172 if ((cell
= cell_list_head()) == NULL
) {
173 return NT_STATUS_INVALID_SERVER_STATE
;
176 /* have to work through these one by one */
177 for (i
= 0; ids
[i
]; i
++) {
179 status
= cell
->provider
->get_sid_from_id(ids
[i
]->sid
,
182 /* Fail if we cannot find any DC */
184 (status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
188 if (!NT_STATUS_IS_OK(status
)) {
189 ids
[i
]->status
= ID_UNMAPPED
;
194 ids
[i
]->status
= ID_MAPPED
;
201 /**********************************************************************
202 *********************************************************************/
204 static NTSTATUS
_idmap_adex_get_id_from_sid(struct
211 bool one_mapped
= false;
212 bool all_mapped
= true;
214 struct likewise_cell
*cell
;
216 /* initialize the status to avoid suprise */
217 for (i
= 0; ids
[i
]; i
++) {
218 ids
[i
]->status
= ID_UNKNOWN
;
221 nt_status
= _idmap_adex_init(dom
);
222 if (!NT_STATUS_IS_OK(nt_status
))
225 if ((cell
= cell_list_head()) == NULL
) {
226 return NT_STATUS_INVALID_SERVER_STATE
;
229 /* have to work through these one by one */
230 for (i
= 0; ids
[i
]; i
++) {
232 status
= cell
->provider
->get_id_from_sid(&ids
[i
]->xid
.id
,
235 /* Fail if we cannot find any DC */
237 (status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
241 if (!NT_STATUS_IS_OK(status
)) {
242 ids
[i
]->status
= ID_UNMAPPED
;
247 ids
[i
]->status
= ID_MAPPED
;
258 /**********************************************************************
259 *********************************************************************/
261 static NTSTATUS
_nss_adex_init(struct nss_domain_entry
264 return _idmap_adex_init(NULL
);
267 /**********************************************************************
268 *********************************************************************/
270 static NTSTATUS
_nss_adex_get_info(struct
272 const struct dom_sid
* sid
,
274 const char **homedir
,
276 const char **gecos
, gid_t
* p_gid
)
279 struct likewise_cell
*cell
;
281 nt_status
= _idmap_adex_init(NULL
);
282 if (!NT_STATUS_IS_OK(nt_status
))
285 if ((cell
= cell_list_head()) == NULL
) {
286 return NT_STATUS_INVALID_SERVER_STATE
;
289 return cell
->provider
->get_nss_info(sid
, ctx
, homedir
,
290 shell
, gecos
, p_gid
);
293 /**********************************************************************
294 *********************************************************************/
296 static NTSTATUS
_nss_adex_map_to_alias(TALLOC_CTX
* mem_ctx
,
297 struct nss_domain_entry
*e
,
298 const char *name
, char **alias
)
300 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
301 struct likewise_cell
*cell
= NULL
;
303 nt_status
= _idmap_adex_init(NULL
);
304 BAIL_ON_NTSTATUS_ERROR(nt_status
);
306 if ((cell
= cell_list_head()) == NULL
) {
307 nt_status
= NT_STATUS_INVALID_SERVER_STATE
;
308 BAIL_ON_NTSTATUS_ERROR(nt_status
);
311 nt_status
= cell
->provider
->map_to_alias(mem_ctx
, e
->domain
,
314 /* go ahead and allow the cache mgr to mark this in
317 if (!NT_STATUS_IS_OK(nt_status
))
318 nt_status
= NT_STATUS_NONE_MAPPED
;
324 /**********************************************************************
325 *********************************************************************/
327 static NTSTATUS
_nss_adex_map_from_alias(TALLOC_CTX
* mem_ctx
,
328 struct nss_domain_entry
*e
,
329 const char *alias
, char **name
)
331 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
332 struct likewise_cell
*cell
= NULL
;
334 nt_status
= _idmap_adex_init(NULL
);
335 BAIL_ON_NTSTATUS_ERROR(nt_status
);
337 if ((cell
= cell_list_head()) == NULL
) {
338 nt_status
= NT_STATUS_INVALID_SERVER_STATE
;
339 BAIL_ON_NTSTATUS_ERROR(nt_status
);
343 nt_status
= cell
->provider
->map_from_alias(mem_ctx
, e
->domain
,
346 /* go ahead and allow the cache mgr to mark this in
349 if (!NT_STATUS_IS_OK(nt_status
))
350 nt_status
= NT_STATUS_NONE_MAPPED
;
356 /**********************************************************************
357 *********************************************************************/
359 static NTSTATUS
_nss_adex_close(void)
361 return NT_STATUS_NOT_IMPLEMENTED
;
364 /**********************************************************************
365 *********************************************************************/
367 static struct idmap_methods adex_idmap_methods
= {
369 .init
= _idmap_adex_init
,
370 .unixids_to_sids
= _idmap_adex_get_sid_from_id
,
371 .sids_to_unixids
= _idmap_adex_get_id_from_sid
,
373 static struct nss_info_methods adex_nss_methods
= {
374 .init
= _nss_adex_init
,
375 .get_nss_info
= _nss_adex_get_info
,
376 .map_to_alias
= _nss_adex_map_to_alias
,
377 .map_from_alias
= _nss_adex_map_from_alias
,
378 .close_fn
= _nss_adex_close
381 /**********************************************************************
382 Register with the idmap and idmap_nss subsystems. We have to protect
383 against the idmap and nss_info interfaces being in a half-registered
385 **********************************************************************/
386 NTSTATUS
samba_init_module(void)
388 static NTSTATUS idmap_status
= NT_STATUS_UNSUCCESSFUL
;
389 static NTSTATUS nss_status
= NT_STATUS_UNSUCCESSFUL
;
390 if (!NT_STATUS_IS_OK(idmap_status
)) {
392 smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
393 "adex", &adex_idmap_methods
);
394 if (!NT_STATUS_IS_OK(idmap_status
)) {
396 ("idmap_centeris_init: Failed to register the adex"
402 if (!NT_STATUS_IS_OK(nss_status
)) {
404 smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION
,
405 "adex", &adex_nss_methods
);
406 if (!NT_STATUS_IS_OK(nss_status
)) {
408 ("idmap_adex_init: Failed to register the adex"