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"
33 NTSTATUS init_module(void);
39 /********************************************************************
40 Basic init function responsible for determining our current mode
41 (standalone or using Centeris Cells). This must return success or
42 it will be dropped from the idmap backend list.
43 *******************************************************************/
45 static NTSTATUS _idmap_adex_init(struct idmap_domain *dom,
48 ADS_STRUCT *ads = NULL;
50 static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
51 struct dom_sid domain_sid;
53 struct sockaddr_storage ip;
54 struct likewise_cell *lwcell;
56 if (NT_STATUS_IS_OK(init_status))
59 /* Silently fail if we are not a member server in security = ads */
61 if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
62 (lp_security() != SEC_ADS)) {
63 init_status = NT_STATUS_INVALID_SERVER_STATE;
64 BAIL_ON_NTSTATUS_ERROR(init_status);
67 /* fetch our domain SID first */
69 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
70 init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
71 BAIL_ON_NTSTATUS_ERROR(init_status);
74 /* reuse the same ticket cache as winbindd */
76 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
78 /* Establish a connection to a DC */
80 if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) {
81 init_status = NT_STATUS_NO_MEMORY;
82 BAIL_ON_NTSTATUS_ERROR(init_status);
86 secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
87 ads->auth.realm = SMB_STRDUP(lp_realm());
89 /* get the DC name here to setup the server affinity cache and
92 get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip);
94 status = ads_connect(ads);
95 if (!ADS_ERR_OK(status)) {
96 DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
99 init_status = ads_ntstatus(status);
100 BAIL_ON_NTSTATUS_ERROR(init_status);
103 /* Find out cell membership */
105 init_status = cell_locate_membership(ads);
106 if (!NT_STATUS_IS_OK(init_status)) {
107 DEBUG(0,("LWI: Fail to locate cell membership (%s).",
108 nt_errstr(init_status)));
112 /* Fill in the cell information */
114 lwcell = cell_list_head();
116 init_status = cell_lookup_settings(lwcell);
117 BAIL_ON_NTSTATUS_ERROR(init_status);
119 /* Miscellaneous setup. E.g. set up the list of GC
120 servers and domain list for our forest (does not actually
123 init_status = gc_init_list();
124 BAIL_ON_NTSTATUS_ERROR(init_status);
126 init_status = domain_init_list();
127 BAIL_ON_NTSTATUS_ERROR(init_status);
130 if (!NT_STATUS_IS_OK(init_status)) {
131 DEBUG(1,("Likewise initialization failed (%s)\n",
132 nt_errstr(init_status)));
137 if (!NT_STATUS_IS_OK(init_status)) {
140 /* init_status stores the failure reason but we need to
141 return success or else idmap_init() will drop us from the
146 init_status = NT_STATUS_OK;
151 /**********************************************************************
152 *********************************************************************/
154 static NTSTATUS _idmap_adex_get_sid_from_id(struct
161 bool one_mapped = false;
162 bool all_mapped = true;
164 struct likewise_cell *cell;
166 /* initialize the status to avoid suprise */
167 for (i = 0; ids[i]; i++) {
168 ids[i]->status = ID_UNKNOWN;
171 nt_status = _idmap_adex_init(dom, NULL);
172 if (!NT_STATUS_IS_OK(nt_status))
175 if ((cell = cell_list_head()) == NULL) {
176 return NT_STATUS_INVALID_SERVER_STATE;
179 /* have to work through these one by one */
180 for (i = 0; ids[i]; i++) {
182 status = cell->provider->get_sid_from_id(ids[i]->sid,
185 /* Fail if we cannot find any DC */
187 (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
191 if (!NT_STATUS_IS_OK(status)) {
192 ids[i]->status = ID_UNMAPPED;
197 ids[i]->status = ID_MAPPED;
204 /**********************************************************************
205 *********************************************************************/
207 static NTSTATUS _idmap_adex_get_id_from_sid(struct
214 bool one_mapped = false;
215 bool all_mapped = true;
217 struct likewise_cell *cell;
219 /* initialize the status to avoid suprise */
220 for (i = 0; ids[i]; i++) {
221 ids[i]->status = ID_UNKNOWN;
224 nt_status = _idmap_adex_init(dom, NULL);
225 if (!NT_STATUS_IS_OK(nt_status))
228 if ((cell = cell_list_head()) == NULL) {
229 return NT_STATUS_INVALID_SERVER_STATE;
232 /* have to work through these one by one */
233 for (i = 0; ids[i]; i++) {
235 status = cell->provider->get_id_from_sid(&ids[i]->xid.id,
238 /* Fail if we cannot find any DC */
240 (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
244 if (!NT_STATUS_IS_OK(status)) {
245 ids[i]->status = ID_UNMAPPED;
250 ids[i]->status = ID_MAPPED;
257 /**********************************************************************
258 *********************************************************************/
260 static NTSTATUS _idmap_adex_close(struct idmap_domain
263 /* FIXME! need to do cleanup here */
272 /**********************************************************************
273 *********************************************************************/
275 static NTSTATUS _nss_adex_init(struct nss_domain_entry
278 return _idmap_adex_init(NULL, NULL);
281 /**********************************************************************
282 *********************************************************************/
284 static NTSTATUS _nss_adex_get_info(struct
286 const struct dom_sid * sid,
290 const char **homedir,
292 const char **gecos, gid_t * p_gid)
295 struct likewise_cell *cell;
297 nt_status = _idmap_adex_init(NULL, NULL);
298 if (!NT_STATUS_IS_OK(nt_status))
301 if ((cell = cell_list_head()) == NULL) {
302 return NT_STATUS_INVALID_SERVER_STATE;
305 return cell->provider->get_nss_info(sid, ctx, homedir,
306 shell, gecos, p_gid);
309 /**********************************************************************
310 *********************************************************************/
312 static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx,
313 struct nss_domain_entry *e,
314 const char *name, char **alias)
316 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
317 struct likewise_cell *cell = NULL;
319 nt_status = _idmap_adex_init(NULL, NULL);
320 BAIL_ON_NTSTATUS_ERROR(nt_status);
322 if ((cell = cell_list_head()) == NULL) {
323 nt_status = NT_STATUS_INVALID_SERVER_STATE;
324 BAIL_ON_NTSTATUS_ERROR(nt_status);
327 nt_status = cell->provider->map_to_alias(mem_ctx, e->domain,
330 /* go ahead and allow the cache mgr to mark this in
333 if (!NT_STATUS_IS_OK(nt_status))
334 nt_status = NT_STATUS_NONE_MAPPED;
340 /**********************************************************************
341 *********************************************************************/
343 static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx,
344 struct nss_domain_entry *e,
345 const char *alias, char **name)
347 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
348 struct likewise_cell *cell = NULL;
350 nt_status = _idmap_adex_init(NULL, NULL);
351 BAIL_ON_NTSTATUS_ERROR(nt_status);
353 if ((cell = cell_list_head()) == NULL) {
354 nt_status = NT_STATUS_INVALID_SERVER_STATE;
355 BAIL_ON_NTSTATUS_ERROR(nt_status);
359 nt_status = cell->provider->map_from_alias(mem_ctx, e->domain,
362 /* go ahead and allow the cache mgr to mark this in
365 if (!NT_STATUS_IS_OK(nt_status))
366 nt_status = NT_STATUS_NONE_MAPPED;
372 /**********************************************************************
373 *********************************************************************/
375 static NTSTATUS _nss_adex_close(void)
377 return NT_STATUS_NOT_IMPLEMENTED;
380 /**********************************************************************
381 *********************************************************************/
383 static struct idmap_methods adex_idmap_methods = {
385 .init = _idmap_adex_init,
386 .unixids_to_sids = _idmap_adex_get_sid_from_id,
387 .sids_to_unixids = _idmap_adex_get_id_from_sid,
388 .close_fn = _idmap_adex_close
390 static struct nss_info_methods adex_nss_methods = {
391 .init = _nss_adex_init,
392 .get_nss_info = _nss_adex_get_info,
393 .map_to_alias = _nss_adex_map_to_alias,
394 .map_from_alias = _nss_adex_map_from_alias,
395 .close_fn = _nss_adex_close
398 /**********************************************************************
399 Register with the idmap and idmap_nss subsystems. We have to protect
400 against the idmap and nss_info interfaces being in a half-registered
402 **********************************************************************/
403 NTSTATUS idmap_adex_init(void)
405 static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
406 static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
407 if (!NT_STATUS_IS_OK(idmap_status)) {
409 smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
410 "adex", &adex_idmap_methods);
411 if (!NT_STATUS_IS_OK(idmap_status)) {
413 ("idmap_centeris_init: Failed to register the adex"
419 if (!NT_STATUS_IS_OK(nss_status)) {
421 smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
422 "adex", &adex_nss_methods);
423 if (!NT_STATUS_IS_OK(nss_status)) {
425 ("idmap_adex_init: Failed to register the adex"