mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
ad0a07c531
Using the standard macro makes it easier to move code into common, as TALLOC_ZERO_P isn't standard talloc.
289 lines
6.9 KiB
C
289 lines
6.9 KiB
C
/*
|
|
* idmap_adex: Domain search interface
|
|
*
|
|
* Copyright (C) Gerald (Jerry) Carter 2007-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 "ads.h"
|
|
#include "idmap.h"
|
|
#include "idmap_adex.h"
|
|
|
|
#undef DBGC_CLASS
|
|
#define DBGC_CLASS DBGC_IDMAP
|
|
|
|
struct dc_info {
|
|
struct dc_info *prev, *next;
|
|
char *dns_name;
|
|
struct likewise_cell *domain_cell;
|
|
};
|
|
|
|
static struct dc_info *_dc_server_list = NULL;
|
|
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
static struct dc_info *dc_list_head(void)
|
|
{
|
|
return _dc_server_list;
|
|
}
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
static NTSTATUS dc_add_domain(const char *domain)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
struct dc_info *dc = NULL;
|
|
|
|
if (!domain) {
|
|
return NT_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
DEBUG(10,("dc_add_domain: Attempting to add domain %s\n", domain));
|
|
|
|
/* Check for duplicates */
|
|
|
|
dc = dc_list_head();
|
|
while (dc) {
|
|
if (strequal (dc->dns_name, domain))
|
|
break;
|
|
dc = dc->next;
|
|
}
|
|
|
|
if (dc) {
|
|
DEBUG(10,("dc_add_domain: %s already in list\n", domain));
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
dc = talloc_zero(NULL, struct dc_info);
|
|
BAIL_ON_PTR_ERROR(dc, nt_status);
|
|
|
|
dc->dns_name = talloc_strdup(dc, domain);
|
|
BAIL_ON_PTR_ERROR(dc->dns_name, nt_status);
|
|
|
|
DLIST_ADD_END(_dc_server_list, dc, struct dc_info*);
|
|
|
|
nt_status = NT_STATUS_OK;
|
|
|
|
DEBUG(5,("dc_add_domain: Successfully added %s\n", domain));
|
|
|
|
done:
|
|
if (!NT_STATUS_IS_OK(nt_status)) {
|
|
talloc_destroy(dc);
|
|
DEBUG(0,("LWI: Failed to add new DC connection for %s (%s)\n",
|
|
domain, nt_errstr(nt_status)));
|
|
}
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
static void dc_server_list_destroy(void)
|
|
{
|
|
struct dc_info *dc = dc_list_head();
|
|
|
|
while (dc) {
|
|
struct dc_info *p = dc->next;
|
|
|
|
cell_destroy(dc->domain_cell);
|
|
talloc_destroy(dc);
|
|
|
|
dc = p;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
NTSTATUS domain_init_list(void)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
struct winbindd_tdc_domain *domains = NULL;
|
|
size_t num_domains = 0;
|
|
int i;
|
|
|
|
if (_dc_server_list != NULL) {
|
|
dc_server_list_destroy();
|
|
}
|
|
|
|
/* Add our domain */
|
|
|
|
nt_status = dc_add_domain(lp_realm());
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
|
|
if (!wcache_tdc_fetch_list(&domains, &num_domains)) {
|
|
nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
}
|
|
|
|
/* Add all domains with an incoming trust path */
|
|
|
|
for (i=0; i<num_domains; i++) {
|
|
uint32_t flags = (NETR_TRUST_FLAG_INBOUND|NETR_TRUST_FLAG_IN_FOREST);
|
|
|
|
/* We just require one of the flags to be set here */
|
|
|
|
if (domains[i].trust_flags & flags) {
|
|
nt_status = dc_add_domain(domains[i].dns_name);
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
}
|
|
}
|
|
|
|
nt_status = NT_STATUS_OK;
|
|
|
|
done:
|
|
if (!NT_STATUS_IS_OK(nt_status)) {
|
|
DEBUG(2,("LWI: Failed to initialize DC list (%s)\n",
|
|
nt_errstr(nt_status)));
|
|
}
|
|
|
|
TALLOC_FREE(domains);
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
/********************************************************************
|
|
*******************************************************************/
|
|
|
|
static NTSTATUS dc_do_search(struct dc_info *dc,
|
|
const char *search_base,
|
|
int scope,
|
|
const char *expr,
|
|
const char **attrs,
|
|
LDAPMessage ** msg)
|
|
{
|
|
ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
|
|
status = cell_do_search(dc->domain_cell, search_base,
|
|
scope, expr, attrs, msg);
|
|
nt_status = ads_ntstatus(status);
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
static struct dc_info *dc_find_domain(const char *dns_domain)
|
|
{
|
|
struct dc_info *dc = dc_list_head();
|
|
|
|
if (!dc)
|
|
return NULL;
|
|
|
|
while (dc) {
|
|
if (strequal(dc->dns_name, dns_domain)) {
|
|
return dc;
|
|
}
|
|
|
|
dc = dc->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**********************************************************************
|
|
*********************************************************************/
|
|
|
|
NTSTATUS dc_search_domains(struct likewise_cell **cell,
|
|
LDAPMessage **msg,
|
|
const char *dn,
|
|
const struct dom_sid *sid)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
TALLOC_CTX *frame = talloc_stackframe();
|
|
char *dns_domain;
|
|
const char *attrs[] = { "*", NULL };
|
|
struct dc_info *dc = NULL;
|
|
const char *base = NULL;
|
|
|
|
if (!dn || !*dn) {
|
|
nt_status = NT_STATUS_INVALID_PARAMETER;
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
}
|
|
|
|
dns_domain = cell_dn_to_dns(dn);
|
|
BAIL_ON_PTR_ERROR(dns_domain, nt_status);
|
|
|
|
if ((dc = dc_find_domain(dns_domain)) == NULL) {
|
|
nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
}
|
|
|
|
/* Reparse the cell settings for the domain if necessary */
|
|
|
|
if (!dc->domain_cell) {
|
|
char *base_dn;
|
|
|
|
base_dn = ads_build_dn(dc->dns_name);
|
|
BAIL_ON_PTR_ERROR(base_dn, nt_status);
|
|
|
|
nt_status = cell_connect_dn(&dc->domain_cell, base_dn);
|
|
SAFE_FREE(base_dn);
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
|
|
nt_status = cell_lookup_settings(dc->domain_cell);
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
|
|
/* By definition this is already part of a larger
|
|
forest-wide search scope */
|
|
|
|
cell_set_flags(dc->domain_cell, LWCELL_FLAG_SEARCH_FOREST);
|
|
}
|
|
|
|
/* Check whether we are operating in non-schema or RFC2307
|
|
mode */
|
|
|
|
if (cell_flags(dc->domain_cell) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
|
|
nt_status = dc_do_search(dc, dn, LDAP_SCOPE_BASE,
|
|
"(objectclass=*)", attrs, msg);
|
|
} else {
|
|
const char *sid_str = NULL;
|
|
char *filter = NULL;
|
|
|
|
sid_str = sid_string_talloc(frame, sid);
|
|
BAIL_ON_PTR_ERROR(sid_str, nt_status);
|
|
|
|
filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
|
|
sid_str);
|
|
BAIL_ON_PTR_ERROR(filter, nt_status);
|
|
|
|
base = cell_search_base(dc->domain_cell);
|
|
BAIL_ON_PTR_ERROR(base, nt_status);
|
|
|
|
nt_status = dc_do_search(dc, base, LDAP_SCOPE_SUBTREE,
|
|
filter, attrs, msg);
|
|
}
|
|
BAIL_ON_NTSTATUS_ERROR(nt_status);
|
|
|
|
*cell = dc->domain_cell;
|
|
|
|
done:
|
|
talloc_destroy(discard_const_p(char, base));
|
|
talloc_destroy(frame);
|
|
|
|
return nt_status;
|
|
}
|