ldb: bump version due to header and internal implementation changes
[Samba/bb.git] / source3 / winbindd / idmap_adex / domain_util.c
blob99dc0cca658affd8e69f2e55148e9c28dd5ebfe5
1 /*
2 * idmap_adex: Domain search interface
4 * Copyright (C) Gerald (Jerry) Carter 2007-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.
21 #include "includes.h"
22 #include "ads.h"
23 #include "idmap.h"
24 #include "idmap_adex.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_IDMAP
29 struct dc_info {
30 struct dc_info *prev, *next;
31 char *dns_name;
32 struct likewise_cell *domain_cell;
35 static struct dc_info *_dc_server_list = NULL;
38 /**********************************************************************
39 *********************************************************************/
41 static struct dc_info *dc_list_head(void)
43 return _dc_server_list;
46 /**********************************************************************
47 *********************************************************************/
49 static NTSTATUS dc_add_domain(const char *domain)
51 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
52 struct dc_info *dc = NULL;
54 if (!domain) {
55 return NT_STATUS_INVALID_PARAMETER;
58 DEBUG(10,("dc_add_domain: Attempting to add domain %s\n", domain));
60 /* Check for duplicates */
62 dc = dc_list_head();
63 while (dc) {
64 if (strequal (dc->dns_name, domain))
65 break;
66 dc = dc->next;
69 if (dc) {
70 DEBUG(10,("dc_add_domain: %s already in list\n", domain));
71 return NT_STATUS_OK;
74 dc = talloc_zero(NULL, struct dc_info);
75 BAIL_ON_PTR_ERROR(dc, nt_status);
77 dc->dns_name = talloc_strdup(dc, domain);
78 BAIL_ON_PTR_ERROR(dc->dns_name, nt_status);
80 DLIST_ADD_END(_dc_server_list, dc, struct dc_info*);
82 nt_status = NT_STATUS_OK;
84 DEBUG(5,("dc_add_domain: Successfully added %s\n", domain));
86 done:
87 if (!NT_STATUS_IS_OK(nt_status)) {
88 talloc_destroy(dc);
89 DEBUG(0,("LWI: Failed to add new DC connection for %s (%s)\n",
90 domain, nt_errstr(nt_status)));
93 return nt_status;
96 /**********************************************************************
97 *********************************************************************/
99 static void dc_server_list_destroy(void)
101 struct dc_info *dc = dc_list_head();
103 while (dc) {
104 struct dc_info *p = dc->next;
106 cell_destroy(dc->domain_cell);
107 talloc_destroy(dc);
109 dc = p;
112 return;
116 /**********************************************************************
117 *********************************************************************/
119 NTSTATUS domain_init_list(void)
121 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
122 struct winbindd_tdc_domain *domains = NULL;
123 size_t num_domains = 0;
124 int i;
126 if (_dc_server_list != NULL) {
127 dc_server_list_destroy();
130 /* Add our domain */
132 nt_status = dc_add_domain(lp_realm());
133 BAIL_ON_NTSTATUS_ERROR(nt_status);
135 if (!wcache_tdc_fetch_list(&domains, &num_domains)) {
136 nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
137 BAIL_ON_NTSTATUS_ERROR(nt_status);
140 /* Add all domains with an incoming trust path */
142 for (i=0; i<num_domains; i++) {
143 uint32_t flags = (NETR_TRUST_FLAG_INBOUND|NETR_TRUST_FLAG_IN_FOREST);
145 /* We just require one of the flags to be set here */
147 if (domains[i].trust_flags & flags) {
148 nt_status = dc_add_domain(domains[i].dns_name);
149 BAIL_ON_NTSTATUS_ERROR(nt_status);
153 nt_status = NT_STATUS_OK;
155 done:
156 if (!NT_STATUS_IS_OK(nt_status)) {
157 DEBUG(2,("LWI: Failed to initialize DC list (%s)\n",
158 nt_errstr(nt_status)));
161 TALLOC_FREE(domains);
163 return nt_status;
166 /********************************************************************
167 *******************************************************************/
169 static NTSTATUS dc_do_search(struct dc_info *dc,
170 const char *search_base,
171 int scope,
172 const char *expr,
173 const char **attrs,
174 LDAPMessage ** msg)
176 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
177 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
179 status = cell_do_search(dc->domain_cell, search_base,
180 scope, expr, attrs, msg);
181 nt_status = ads_ntstatus(status);
183 return nt_status;
186 /**********************************************************************
187 *********************************************************************/
189 static struct dc_info *dc_find_domain(const char *dns_domain)
191 struct dc_info *dc = dc_list_head();
193 if (!dc)
194 return NULL;
196 while (dc) {
197 if (strequal(dc->dns_name, dns_domain)) {
198 return dc;
201 dc = dc->next;
204 return NULL;
207 /**********************************************************************
208 *********************************************************************/
210 NTSTATUS dc_search_domains(struct likewise_cell **cell,
211 LDAPMessage **msg,
212 const char *dn,
213 const struct dom_sid *sid)
215 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
216 TALLOC_CTX *frame = talloc_stackframe();
217 char *dns_domain;
218 const char *attrs[] = { "*", NULL };
219 struct dc_info *dc = NULL;
220 const char *base = NULL;
222 if (!dn || !*dn) {
223 nt_status = NT_STATUS_INVALID_PARAMETER;
224 BAIL_ON_NTSTATUS_ERROR(nt_status);
227 dns_domain = cell_dn_to_dns(dn);
228 BAIL_ON_PTR_ERROR(dns_domain, nt_status);
230 if ((dc = dc_find_domain(dns_domain)) == NULL) {
231 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
232 BAIL_ON_NTSTATUS_ERROR(nt_status);
235 /* Reparse the cell settings for the domain if necessary */
237 if (!dc->domain_cell) {
238 char *base_dn;
240 base_dn = ads_build_dn(dc->dns_name);
241 BAIL_ON_PTR_ERROR(base_dn, nt_status);
243 nt_status = cell_connect_dn(&dc->domain_cell, base_dn);
244 SAFE_FREE(base_dn);
245 BAIL_ON_NTSTATUS_ERROR(nt_status);
247 nt_status = cell_lookup_settings(dc->domain_cell);
248 BAIL_ON_NTSTATUS_ERROR(nt_status);
250 /* By definition this is already part of a larger
251 forest-wide search scope */
253 cell_set_flags(dc->domain_cell, LWCELL_FLAG_SEARCH_FOREST);
256 /* Check whether we are operating in non-schema or RFC2307
257 mode */
259 if (cell_flags(dc->domain_cell) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
260 nt_status = dc_do_search(dc, dn, LDAP_SCOPE_BASE,
261 "(objectclass=*)", attrs, msg);
262 } else {
263 const char *sid_str = NULL;
264 char *filter = NULL;
266 sid_str = sid_string_talloc(frame, sid);
267 BAIL_ON_PTR_ERROR(sid_str, nt_status);
269 filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
270 sid_str);
271 BAIL_ON_PTR_ERROR(filter, nt_status);
273 base = cell_search_base(dc->domain_cell);
274 BAIL_ON_PTR_ERROR(base, nt_status);
276 nt_status = dc_do_search(dc, base, LDAP_SCOPE_SUBTREE,
277 filter, attrs, msg);
279 BAIL_ON_NTSTATUS_ERROR(nt_status);
281 *cell = dc->domain_cell;
283 done:
284 talloc_destroy(discard_const_p(char, base));
285 talloc_destroy(frame);
287 return nt_status;