1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/source3/winbindd/idmap_adex/idmap_adex.c
2009-08-03 22:48:45 +02:00

472 lines
12 KiB
C

/*
* 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;
/* initialize the status to avoid suprise */
for (i = 0; ids[i]; i++) {
ids[i]->status = ID_UNKNOWN;
}
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;
/* initialize the status to avoid suprise */
for (i = 0; ids[i]; i++) {
ids[i]->status = ID_UNKNOWN;
}
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,
const char **homedir,
const char **shell,
const 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,
struct nss_domain_entry *e,
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, e->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,
struct nss_domain_entry *e,
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, e->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();
}