diff options
Diffstat (limited to 'source3/winbindd/idmap_adex/idmap_adex.c')
-rw-r--r-- | source3/winbindd/idmap_adex/idmap_adex.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/source3/winbindd/idmap_adex/idmap_adex.c b/source3/winbindd/idmap_adex/idmap_adex.c new file mode 100644 index 0000000000..7596b1cbd8 --- /dev/null +++ b/source3/winbindd/idmap_adex/idmap_adex.c @@ -0,0 +1,460 @@ +/* + * idmap_adex: Support for D Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache" + +NTSTATUS init_module(void); + +/* + * IdMap backend + */ + +/******************************************************************** + Basic init function responsible for determining our current mode + (standalone or using Centeris Cells). This must return success or + it will be dropped from the idmap backend list. + *******************************************************************/ + +static NTSTATUS _idmap_adex_init(struct idmap_domain *dom, + const char *params) +{ + ADS_STRUCT *ads = NULL; + ADS_STATUS status; + static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + DOM_SID domain_sid; + fstring dcname; + struct sockaddr_storage ip; + struct likewise_cell *lwcell; + + if (NT_STATUS_IS_OK(init_status)) + return NT_STATUS_OK; + + /* Silently fail if we are not a member server in security = ads */ + + if ((lp_server_role() != ROLE_DOMAIN_MEMBER) || + (lp_security() != SEC_ADS)) { + init_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + /* fetch our domain SID first */ + + if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { + init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + /* reuse the same ticket cache as winbindd */ + + setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); + + /* Establish a connection to a DC */ + + if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) { + init_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + ads->auth.password = + secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + ads->auth.realm = SMB_STRDUP(lp_realm()); + + /* get the DC name here to setup the server affinity cache and + local krb5.conf */ + + get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip); + + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n", + ads_errstr(status))); + } + init_status = ads_ntstatus(status); + BAIL_ON_NTSTATUS_ERROR(init_status); + + + /* Find out cell membership */ + + init_status = cell_locate_membership(ads); + if (!NT_STATUS_IS_OK(init_status)) { + DEBUG(0,("LWI: Fail to locate cell membership (%s).", + nt_errstr(init_status))); + goto done; + } + + /* Fill in the cell information */ + + lwcell = cell_list_head(); + + init_status = cell_lookup_settings(lwcell); + BAIL_ON_NTSTATUS_ERROR(init_status); + + /* Miscellaneous setup. E.g. set up the list of GC + servers and domain list for our forest (does not actually + connect). */ + + init_status = gc_init_list(); + BAIL_ON_NTSTATUS_ERROR(init_status); + + init_status = domain_init_list(); + BAIL_ON_NTSTATUS_ERROR(init_status); + +done: + if (!NT_STATUS_IS_OK(init_status)) { + DEBUG(1,("Likewise initialization failed (%s)\n", + nt_errstr(init_status))); + } + + /* cleanup */ + + if (!NT_STATUS_IS_OK(init_status)) { + cell_list_destroy(); + + /* init_status stores the failure reason but we need to + return success or else idmap_init() will drop us from the + backend list */ + return NT_STATUS_OK; + } + + init_status = NT_STATUS_OK; + + return init_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_get_sid_from_id(struct + idmap_domain + *dom, struct + id_map + **ids) +{ + int i; + bool one_mapped = false; + bool all_mapped = true; + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(dom, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + /* have to work through these one by one */ + for (i = 0; ids[i]; i++) { + NTSTATUS status; + status = cell->provider->get_sid_from_id(ids[i]->sid, + ids[i]->xid.id, + ids[i]->xid.type); + /* Fail if we cannot find any DC */ + if (NT_STATUS_EQUAL + (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + return status; + } + + if (!NT_STATUS_IS_OK(status)) { + ids[i]->status = ID_UNMAPPED; + all_mapped = false; + continue; + } + + ids[i]->status = ID_MAPPED; + one_mapped = true; + } + + return NT_STATUS_OK; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_get_id_from_sid(struct + idmap_domain + *dom, struct + id_map + **ids) +{ + int i; + bool one_mapped = false; + bool all_mapped = true; + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(dom, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + /* have to work through these one by one */ + for (i = 0; ids[i]; i++) { + NTSTATUS status; + status = cell->provider->get_id_from_sid(&ids[i]->xid.id, + &ids[i]->xid. + type, ids[i]->sid); + /* Fail if we cannot find any DC */ + if (NT_STATUS_EQUAL + (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + return status; + } + + if (!NT_STATUS_IS_OK(status)) { + ids[i]->status = ID_UNMAPPED; + all_mapped = false; + continue; + } + + ids[i]->status = ID_MAPPED; + one_mapped = true; + } + + return NT_STATUS_OK; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_set_mapping(struct + idmap_domain + *dom, const struct + id_map *map) +{ + DEBUG(0, ("_idmap_adex_set_mapping: not implemented\n")); + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_remove_mapping(struct + idmap_domain + *dom, const + struct + id_map + *map) +{ + DEBUG(0, ("_idmap_adex_remove_mapping: not implemented\n")); + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_dump(struct idmap_domain + *dom, struct id_map **maps, int *num_map) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_close(struct idmap_domain + *dom) +{ + /* FIXME! need to do cleanup here */ + + return NT_STATUS_OK; +} + +/* + * IdMap NSS plugin + */ + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_init(struct nss_domain_entry + *e) +{ + return _idmap_adex_init(NULL, NULL); +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_get_info(struct + nss_domain_entry *e, + const DOM_SID * sid, + TALLOC_CTX * ctx, + ADS_STRUCT * ads, + LDAPMessage * msg, + char **homedir, + char **shell, char **gecos, gid_t * p_gid) +{ + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + return cell->provider->get_nss_info(sid, ctx, homedir, + shell, gecos, p_gid); +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx, const char + *domain, const char + *name, char **alias) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *cell = NULL; + + nt_status = _idmap_adex_init(NULL, NULL); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if ((cell = cell_list_head()) == NULL) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = cell->provider->map_to_alias(mem_ctx, domain, + name, alias); + + /* go ahead and allow the cache mgr to mark this in + negative cache */ + + if (!NT_STATUS_IS_OK(nt_status)) + nt_status = NT_STATUS_NONE_MAPPED; + +done: + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx, const char + *domain, const char + *alias, char **name) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *cell = NULL; + + nt_status = _idmap_adex_init(NULL, NULL); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if ((cell = cell_list_head()) == NULL) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + + nt_status = cell->provider->map_from_alias(mem_ctx, domain, + alias, name); + + /* go ahead and allow the cache mgr to mark this in + negative cache */ + + if (!NT_STATUS_IS_OK(nt_status)) + nt_status = NT_STATUS_NONE_MAPPED; + +done: + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_close(void) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static struct idmap_methods adex_idmap_methods = { + + .init = _idmap_adex_init, + .unixids_to_sids = _idmap_adex_get_sid_from_id, + .sids_to_unixids = _idmap_adex_get_id_from_sid, + .set_mapping = _idmap_adex_set_mapping, + .remove_mapping = _idmap_adex_remove_mapping, + .dump_data = _idmap_adex_dump, + .close_fn = _idmap_adex_close +}; +static struct nss_info_methods adex_nss_methods = { + .init = _nss_adex_init, + .get_nss_info = _nss_adex_get_info, + .map_to_alias = _nss_adex_map_to_alias, + .map_from_alias = _nss_adex_map_from_alias, + .close_fn = _nss_adex_close +}; + +/********************************************************************** + Register with the idmap and idmap_nss subsystems. We have to protect + against the idmap and nss_info interfaces being in a half-registered + state. + **********************************************************************/ +NTSTATUS idmap_adex_init(void) +{ + static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(idmap_status)) { + idmap_status = + smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, + "adex", &adex_idmap_methods); + if (!NT_STATUS_IS_OK(idmap_status)) { + DEBUG(0, + ("idmap_centeris_init: Failed to register the adex" + "idmap plugin.\n")); + return idmap_status; + } + } + + if (!NT_STATUS_IS_OK(nss_status)) { + nss_status = + smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "adex", &adex_nss_methods); + if (!NT_STATUS_IS_OK(nss_status)) { + DEBUG(0, + ("idmap_adex_init: Failed to register the adex" + "nss plugin.\n")); + return nss_status; + } + } + + return NT_STATUS_OK; +} + +static NTSTATUS nss_info_adex_init(void) +{ + return idmap_adex_init(); +} |