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)
47 ADS_STRUCT *ads = NULL;
49 static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
50 struct dom_sid domain_sid;
52 struct sockaddr_storage ip;
53 struct likewise_cell *lwcell;
55 if (NT_STATUS_IS_OK(init_status))
58 /* Silently fail if we are not a member server in security = ads */
60 if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
61 (lp_security() != SEC_ADS)) {
62 init_status = NT_STATUS_INVALID_SERVER_STATE;
63 BAIL_ON_NTSTATUS_ERROR(init_status);
66 /* fetch our domain SID first */
68 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
69 init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
70 BAIL_ON_NTSTATUS_ERROR(init_status);
73 /* reuse the same ticket cache as winbindd */
75 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
77 /* Establish a connection to a DC */
79 if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) {
80 init_status = NT_STATUS_NO_MEMORY;
81 BAIL_ON_NTSTATUS_ERROR(init_status);
85 secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
86 ads->auth.realm = SMB_STRDUP(lp_realm());
88 /* get the DC name here to setup the server affinity cache and
91 get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip);
93 status = ads_connect(ads);
94 if (!ADS_ERR_OK(status)) {
95 DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
98 init_status = ads_ntstatus(status);
99 BAIL_ON_NTSTATUS_ERROR(init_status);
102 /* Find out cell membership */
104 init_status = cell_locate_membership(ads);
105 if (!NT_STATUS_IS_OK(init_status)) {
106 DEBUG(0,("LWI: Fail to locate cell membership (%s).",
107 nt_errstr(init_status)));
111 /* Fill in the cell information */
113 lwcell = cell_list_head();
115 init_status = cell_lookup_settings(lwcell);
116 BAIL_ON_NTSTATUS_ERROR(init_status);
118 /* Miscellaneous setup. E.g. set up the list of GC
119 servers and domain list for our forest (does not actually
122 init_status = gc_init_list();
123 BAIL_ON_NTSTATUS_ERROR(init_status);
125 init_status = domain_init_list();
126 BAIL_ON_NTSTATUS_ERROR(init_status);
129 if (!NT_STATUS_IS_OK(init_status)) {
130 DEBUG(1,("Likewise initialization failed (%s)\n",
131 nt_errstr(init_status)));
136 if (!NT_STATUS_IS_OK(init_status)) {
139 /* init_status stores the failure reason but we need to
140 return success or else idmap_init() will drop us from the
145 init_status = NT_STATUS_OK;
150 /**********************************************************************
151 *********************************************************************/
153 static NTSTATUS _idmap_adex_get_sid_from_id(struct
160 bool one_mapped = false;
161 bool all_mapped = true;
163 struct likewise_cell *cell;
165 /* initialize the status to avoid suprise */
166 for (i = 0; ids[i]; i++) {
167 ids[i]->status = ID_UNKNOWN;
170 nt_status = _idmap_adex_init(dom);
171 if (!NT_STATUS_IS_OK(nt_status))
174 if ((cell = cell_list_head()) == NULL) {
175 return NT_STATUS_INVALID_SERVER_STATE;
178 /* have to work through these one by one */
179 for (i = 0; ids[i]; i++) {
181 status = cell->provider->get_sid_from_id(ids[i]->sid,
184 /* Fail if we cannot find any DC */
186 (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
190 if (!NT_STATUS_IS_OK(status)) {
191 ids[i]->status = ID_UNMAPPED;
196 ids[i]->status = ID_MAPPED;
203 /**********************************************************************
204 *********************************************************************/
206 static NTSTATUS _idmap_adex_get_id_from_sid(struct
213 bool one_mapped = false;
214 bool all_mapped = true;
216 struct likewise_cell *cell;
218 /* initialize the status to avoid suprise */
219 for (i = 0; ids[i]; i++) {
220 ids[i]->status = ID_UNKNOWN;
223 nt_status = _idmap_adex_init(dom);
224 if (!NT_STATUS_IS_OK(nt_status))
227 if ((cell = cell_list_head()) == NULL) {
228 return NT_STATUS_INVALID_SERVER_STATE;
231 /* have to work through these one by one */
232 for (i = 0; ids[i]; i++) {
234 status = cell->provider->get_id_from_sid(&ids[i]->xid.id,
237 /* Fail if we cannot find any DC */
239 (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
243 if (!NT_STATUS_IS_OK(status)) {
244 ids[i]->status = ID_UNMAPPED;
249 ids[i]->status = ID_MAPPED;
260 /**********************************************************************
261 *********************************************************************/
263 static NTSTATUS _nss_adex_init(struct nss_domain_entry
266 return _idmap_adex_init(NULL);
269 /**********************************************************************
270 *********************************************************************/
272 static NTSTATUS _nss_adex_get_info(struct
274 const struct dom_sid * sid,
276 const char **homedir,
278 const char **gecos, gid_t * p_gid)
281 struct likewise_cell *cell;
283 nt_status = _idmap_adex_init(NULL);
284 if (!NT_STATUS_IS_OK(nt_status))
287 if ((cell = cell_list_head()) == NULL) {
288 return NT_STATUS_INVALID_SERVER_STATE;
291 return cell->provider->get_nss_info(sid, ctx, homedir,
292 shell, gecos, p_gid);
295 /**********************************************************************
296 *********************************************************************/
298 static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx,
299 struct nss_domain_entry *e,
300 const char *name, char **alias)
302 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
303 struct likewise_cell *cell = NULL;
305 nt_status = _idmap_adex_init(NULL);
306 BAIL_ON_NTSTATUS_ERROR(nt_status);
308 if ((cell = cell_list_head()) == NULL) {
309 nt_status = NT_STATUS_INVALID_SERVER_STATE;
310 BAIL_ON_NTSTATUS_ERROR(nt_status);
313 nt_status = cell->provider->map_to_alias(mem_ctx, e->domain,
316 /* go ahead and allow the cache mgr to mark this in
319 if (!NT_STATUS_IS_OK(nt_status))
320 nt_status = NT_STATUS_NONE_MAPPED;
326 /**********************************************************************
327 *********************************************************************/
329 static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx,
330 struct nss_domain_entry *e,
331 const char *alias, char **name)
333 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
334 struct likewise_cell *cell = NULL;
336 nt_status = _idmap_adex_init(NULL);
337 BAIL_ON_NTSTATUS_ERROR(nt_status);
339 if ((cell = cell_list_head()) == NULL) {
340 nt_status = NT_STATUS_INVALID_SERVER_STATE;
341 BAIL_ON_NTSTATUS_ERROR(nt_status);
345 nt_status = cell->provider->map_from_alias(mem_ctx, e->domain,
348 /* go ahead and allow the cache mgr to mark this in
351 if (!NT_STATUS_IS_OK(nt_status))
352 nt_status = NT_STATUS_NONE_MAPPED;
358 /**********************************************************************
359 *********************************************************************/
361 static NTSTATUS _nss_adex_close(void)
363 return NT_STATUS_NOT_IMPLEMENTED;
366 /**********************************************************************
367 *********************************************************************/
369 static struct idmap_methods adex_idmap_methods = {
371 .init = _idmap_adex_init,
372 .unixids_to_sids = _idmap_adex_get_sid_from_id,
373 .sids_to_unixids = _idmap_adex_get_id_from_sid,
375 static struct nss_info_methods adex_nss_methods = {
376 .init = _nss_adex_init,
377 .get_nss_info = _nss_adex_get_info,
378 .map_to_alias = _nss_adex_map_to_alias,
379 .map_from_alias = _nss_adex_map_from_alias,
380 .close_fn = _nss_adex_close
383 /**********************************************************************
384 Register with the idmap and idmap_nss subsystems. We have to protect
385 against the idmap and nss_info interfaces being in a half-registered
387 **********************************************************************/
388 NTSTATUS samba_init_module(void)
390 static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
391 static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
392 if (!NT_STATUS_IS_OK(idmap_status)) {
394 smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
395 "adex", &adex_idmap_methods);
396 if (!NT_STATUS_IS_OK(idmap_status)) {
398 ("idmap_centeris_init: Failed to register the adex"
404 if (!NT_STATUS_IS_OK(nss_status)) {
406 smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
407 "adex", &adex_nss_methods);
408 if (!NT_STATUS_IS_OK(nss_status)) {
410 ("idmap_adex_init: Failed to register the adex"