return ((domain->domain_flags & fr_flags) == fr_flags);
}
-/********************************************************************
- rescan our domains looking for new trusted domains
-********************************************************************/
-
-struct trustdom_state {
- struct winbindd_domain *domain;
- struct winbindd_request request;
-};
-
-static void trustdom_list_done(struct tevent_req *req);
-static void rescan_forest_root_trusts( void );
-static void rescan_forest_trusts( void );
-
-static void add_trusted_domains( struct winbindd_domain *domain )
-{
- struct trustdom_state *state;
- struct tevent_req *req;
-
- state = talloc_zero(NULL, struct trustdom_state);
- if (state == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return;
- }
- state->domain = domain;
-
- state->request.length = sizeof(state->request);
- state->request.cmd = WINBINDD_LIST_TRUSTDOM;
-
- req = wb_domain_request_send(state, global_event_context(),
- domain, &state->request);
- if (req == NULL) {
- DEBUG(1, ("wb_domain_request_send failed\n"));
- TALLOC_FREE(state);
- return;
- }
- tevent_req_set_callback(req, trustdom_list_done, state);
-}
-
-static void trustdom_list_done(struct tevent_req *req)
-{
- struct trustdom_state *state = tevent_req_callback_data(
- req, struct trustdom_state);
- struct winbindd_response *response;
- int res, err;
- char *p;
- ptrdiff_t extra_len;
- bool within_forest = false;
- NTSTATUS status;
-
- /*
- * Only when we enumerate our primary domain
- * or our forest root domain, we should keep
- * the NETR_TRUST_FLAG_IN_FOREST flag, in
- * all other cases we need to clear it as the domain
- * is not part of our forest.
- */
- if (state->domain->primary) {
- within_forest = true;
- } else if (domain_is_forest_root(state->domain)) {
- within_forest = true;
- }
-
- res = wb_domain_request_recv(req, state, &response, &err);
- if ((res == -1) || (response->result != WINBINDD_OK)) {
- DBG_WARNING("Could not receive trusts for domain %s\n",
- state->domain->name);
- TALLOC_FREE(state);
- return;
- }
-
- if (response->length < sizeof(struct winbindd_response)) {
- DBG_ERR("ill-formed trustdom response - short length\n");
- TALLOC_FREE(state);
- return;
- }
-
- extra_len = response->length - sizeof(struct winbindd_response);
-
- p = (char *)response->extra_data.data;
-
- while ((p - (char *)response->extra_data.data) < extra_len) {
- struct winbindd_domain *domain = NULL;
- char *name, *q, *sidstr, *alt_name;
- struct dom_sid sid;
- uint32_t trust_type;
- uint32_t trust_attribs;
- uint32_t trust_flags;
- int error = 0;
-
- DBG_DEBUG("parsing response line '%s'\n", p);
-
- name = p;
-
- alt_name = strchr(p, '\\');
- if (alt_name == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- *alt_name = '\0';
- alt_name += 1;
-
- sidstr = strchr(alt_name, '\\');
- if (sidstr == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- *sidstr = '\0';
- sidstr += 1;
-
- /* use the real alt_name if we have one, else pass in NULL */
- if (strequal(alt_name, "(null)")) {
- alt_name = NULL;
- }
-
- q = strtok(sidstr, "\\");
- if (q == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- if (!string_to_sid(&sid, sidstr)) {
- DEBUG(0, ("Got invalid trustdom response\n"));
- break;
- }
-
- q = strtok(NULL, "\\");
- if (q == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- trust_flags = (uint32_t)smb_strtoul(q,
- NULL,
- 10,
- &error,
- SMB_STR_STANDARD);
- if (error != 0) {
- DBG_ERR("Failed to convert trust_flags\n");
- break;
- }
-
- q = strtok(NULL, "\\");
- if (q == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- trust_type = (uint32_t)smb_strtoul(q,
- NULL,
- 10,
- &error,
- SMB_STR_STANDARD);
- if (error != 0) {
- DBG_ERR("Failed to convert trust_type\n");
- break;
- }
-
- q = strtok(NULL, "\n");
- if (q == NULL) {
- DBG_ERR("Got invalid trustdom response\n");
- break;
- }
-
- trust_attribs = (uint32_t)smb_strtoul(q,
- NULL,
- 10,
- &error,
- SMB_STR_STANDARD);
- if (error != 0) {
- DBG_ERR("Failed to convert trust_attribs\n");
- break;
- }
-
- if (!within_forest) {
- trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
- }
-
- if (!state->domain->primary) {
- trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
- }
-
- /*
- * We always call add_trusted_domain() cause on an existing
- * domain structure, it will update the SID if necessary.
- * This is important because we need the SID for sibling
- * domains.
- */
- status = add_trusted_domain(name,
- alt_name,
- &sid,
- trust_type,
- trust_flags,
- trust_attribs,
- SEC_CHAN_NULL,
- find_default_route_domain(),
- &domain);
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
- {
- DBG_NOTICE("add_trusted_domain returned %s\n",
- nt_errstr(status));
- return;
- }
-
- p = q + strlen(q) + 1;
- }
-
- /*
- Cases to consider when scanning trusts:
- (a) we are calling from a child domain (primary && !forest_root)
- (b) we are calling from the root of the forest (primary && forest_root)
- (c) we are calling from a trusted forest domain (!primary
- && !forest_root)
- */
-
- if (state->domain->primary) {
- /* If this is our primary domain and we are not in the
- forest root, we have to scan the root trusts first */
-
- if (!domain_is_forest_root(state->domain))
- rescan_forest_root_trusts();
- else
- rescan_forest_trusts();
-
- } else if (domain_is_forest_root(state->domain)) {
- /* Once we have done root forest trust search, we can
- go on to search the trusted forests */
-
- rescan_forest_trusts();
- }
-
- TALLOC_FREE(state);
-
- return;
-}
-
-/********************************************************************
- Scan the trusts of our forest root
-********************************************************************/
-
-static void rescan_forest_root_trusts( void )
-{
- struct winbindd_tdc_domain *dom_list = NULL;
- size_t num_trusts = 0;
- size_t i;
- NTSTATUS status;
-
- /* The only transitive trusts supported by Windows 2003 AD are
- (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
- first two are handled in forest and listed by
- DsEnumerateDomainTrusts(). Forest trusts are not so we
- have to do that ourselves. */
-
- if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
- return;
-
- for ( i=0; i<num_trusts; i++ ) {
- struct winbindd_domain *d = NULL;
-
- /* Find the forest root. Don't necessarily trust
- the domain_list() as our primary domain may not
- have been initialized. */
-
- if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
- continue;
- }
-
- /* Here's the forest root */
-
- d = find_domain_from_name_noinit( dom_list[i].domain_name );
- if (d == NULL) {
- status = add_trusted_domain(dom_list[i].domain_name,
- dom_list[i].dns_name,
- &dom_list[i].sid,
- dom_list[i].trust_type,
- dom_list[i].trust_flags,
- dom_list[i].trust_attribs,
- SEC_CHAN_NULL,
- find_default_route_domain(),
- &d);
-
- if (!NT_STATUS_IS_OK(status) &&
- NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
- {
- DBG_ERR("add_trusted_domain returned %s\n",
- nt_errstr(status));
- return;
- }
- }
- if (d == NULL) {
- continue;
- }
-
- DEBUG(10,("rescan_forest_root_trusts: Following trust path "
- "for domain tree root %s (%s)\n",
- d->name, d->alt_name ));
-
- d->domain_flags = dom_list[i].trust_flags;
- d->domain_type = dom_list[i].trust_type;
- d->domain_trust_attribs = dom_list[i].trust_attribs;
-
- add_trusted_domains( d );
-
- break;
- }
-
- TALLOC_FREE( dom_list );
-
- return;
-}
-
-/********************************************************************
- scan the transitive forest trusts (not our own)
-********************************************************************/
-
-
-static void rescan_forest_trusts( void )
-{
- struct winbindd_domain *d = NULL;
- struct winbindd_tdc_domain *dom_list = NULL;
- size_t num_trusts = 0;
- size_t i;
- NTSTATUS status;
-
- /* The only transitive trusts supported by Windows 2003 AD are
- (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
- first two are handled in forest and listed by
- DsEnumerateDomainTrusts(). Forest trusts are not so we
- have to do that ourselves. */
-
- if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
- return;
-
- for ( i=0; i<num_trusts; i++ ) {
- uint32_t flags = dom_list[i].trust_flags;
- uint32_t type = dom_list[i].trust_type;
- uint32_t attribs = dom_list[i].trust_attribs;
-
- d = find_domain_from_name_noinit( dom_list[i].domain_name );
-
- /* ignore our primary and internal domains */
-
- if ( d && (d->internal || d->primary ) )
- continue;
-
- if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
- (type == LSA_TRUST_TYPE_UPLEVEL) &&
- (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
- {
- /* add the trusted domain if we don't know
- about it */
-
- if (d == NULL) {
- status = add_trusted_domain(
- dom_list[i].domain_name,
- dom_list[i].dns_name,
- &dom_list[i].sid,
- type,
- flags,
- attribs,
- SEC_CHAN_NULL,
- find_default_route_domain(),
- &d);
- if (!NT_STATUS_IS_OK(status) &&
- NT_STATUS_EQUAL(status,
- NT_STATUS_NO_SUCH_DOMAIN))
- {
- DBG_ERR("add_trusted_domain: %s\n",
- nt_errstr(status));
- return;
- }
- }
-
- if (d == NULL) {
- continue;
- }
-
- DEBUG(10,("Following trust path for domain %s (%s)\n",
- d->name, d->alt_name ));
- add_trusted_domains( d );
- }
- }
-
- TALLOC_FREE( dom_list );
-
- return;
-}
-
-/*********************************************************************
- The process of updating the trusted domain list is a three step
- async process:
- (a) ask our domain
- (b) ask the root domain in our forest
- (c) ask the a DC in any Win2003 trusted forests
-*********************************************************************/
-
-void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
- struct timeval now, void *private_data)
-{
- TALLOC_FREE(te);
-
- /* I use to clear the cache here and start over but that
- caused problems in child processes that needed the
- trust dom list early on. Removing it means we
- could have some trusted domains listed that have been
- removed from our primary domain's DC until a full
- restart. This should be ok since I think this is what
- Windows does as well. */
-
- /* this will only add new domains we didn't already know about
- in the domain_list()*/
-
- add_trusted_domains( find_our_domain() );
-
- te = tevent_add_timer(
- ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
- rescan_trusted_domains, NULL);
- /*
- * If te == NULL, there's not much we can do here. Don't fail, the
- * only thing we miss is new trusted domains.
- */
-
- return;
-}
-
enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{