コード例 #1
0
ファイル: ldap_utils.c プロジェクト: Distrotech/samba
/*
  a wrapper around ldap_search_s that retries depending on the error code
  this is supposed to catch dropped connections and auto-reconnect
*/
static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind_path, int scope, 
					       const char *expr,
					       const char **attrs, void *args,
					       LDAPMessage **res)
{
	ADS_STATUS status = ADS_SUCCESS;
	int count = 3;
	char *bp;

	*res = NULL;

	if (!ads->ldap.ld &&
	    time_mono(NULL) - ads->ldap.last_attempt < ADS_RECONNECT_TIME) {
		return ADS_ERROR(LDAP_SERVER_DOWN);
	}

	bp = SMB_STRDUP(bind_path);

	if (!bp) {
		return ADS_ERROR(LDAP_NO_MEMORY);
	}

	*res = NULL;

	/* when binding anonymously, we cannot use the paged search LDAP
	 * control - Guenther */

	if (ads->auth.flags & ADS_AUTH_ANON_BIND) {
		status = ads_do_search(ads, bp, scope, expr, attrs, res);
	} else {
		status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res);
	}
	if (ADS_ERR_OK(status)) {
               DEBUG(5,("Search for %s in <%s> gave %d replies\n",
                        expr, bp, ads_count_replies(ads, *res)));
		SAFE_FREE(bp);
		return status;
	}

	while (--count) {

		if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && ads->config.ldap_page_size >= 250) {
			int new_page_size = (ads->config.ldap_page_size / 2);
			DEBUG(1, ("Reducing LDAP page size from %d to %d due to IO_TIMEOUT\n",
				  ads->config.ldap_page_size, new_page_size));
			ads->config.ldap_page_size = new_page_size;
		}

		if (*res) 
			ads_msgfree(ads, *res);
		*res = NULL;

		DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n", 
			 ads->config.realm, ads_errstr(status)));

		ads_disconnect(ads);
		status = ads_connect(ads);

		if (!ADS_ERR_OK(status)) {
			DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n",
				 ads_errstr(status)));
			ads_destroy(&ads);
			SAFE_FREE(bp);
			return status;
		}

		*res = NULL;

		/* when binding anonymously, we cannot use the paged search LDAP
		 * control - Guenther */

		if (ads->auth.flags & ADS_AUTH_ANON_BIND) {
			status = ads_do_search(ads, bp, scope, expr, attrs, res);
		} else {
			status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res);
		}

		if (ADS_ERR_OK(status)) {
			DEBUG(5,("Search for filter: %s, base: %s gave %d replies\n",
				 expr, bp, ads_count_replies(ads, *res)));
			SAFE_FREE(bp);
			return status;
		}
	}
        SAFE_FREE(bp);

	if (!ADS_ERR_OK(status)) {
		DEBUG(1,("ads reopen failed after error %s\n", 
			 ads_errstr(status)));
	}
	return status;
}
コード例 #2
0
ファイル: winbindd_ads.c プロジェクト: encukou/samba
static NTSTATUS add_primary_group_members(
	ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
	char ***all_members, size_t *num_all_members)
{
	char *filter;
	NTSTATUS status = NT_STATUS_NO_MEMORY;
	ADS_STATUS rc;
	const char *attrs[] = { "dn", NULL };
	LDAPMessage *res = NULL;
	LDAPMessage *msg;
	char **members;
	size_t num_members;
	ads_control args;

	filter = talloc_asprintf(
		mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
		(unsigned)rid);
	if (filter == NULL) {
		goto done;
	}

	args.control = ADS_EXTENDED_DN_OID;
	args.val = ADS_EXTENDED_DN_HEX_STRING;
	args.critical = True;

	rc = ads_do_search_all_args(ads, ads->config.bind_path,
				    LDAP_SCOPE_SUBTREE, filter, attrs, &args,
				    &res);

	if (!ADS_ERR_OK(rc)) {
		status = ads_ntstatus(rc);
		DEBUG(1,("%s: ads_search: %s\n", __func__, ads_errstr(rc)));
		goto done;
	}
	if (res == NULL) {
		DEBUG(1,("%s: ads_search returned NULL res\n", __func__));
		goto done;
	}

	num_members = ads_count_replies(ads, res);

	DEBUG(10, ("%s: Got %ju primary group members\n", __func__,
		   (uintmax_t)num_members));

	if (num_members == 0) {
		status = NT_STATUS_OK;
		goto done;
	}

	members = talloc_realloc(mem_ctx, *all_members, char *,
				 *num_all_members + num_members);
	if (members == NULL) {
		DEBUG(1, ("%s: talloc_realloc failed\n", __func__));
		goto done;
	}
	*all_members = members;

	for (msg = ads_first_entry(ads, res); msg != NULL;
	     msg = ads_next_entry(ads, msg)) {
		char *dn;

		dn = ads_get_dn(ads, members, msg);
		if (dn == NULL) {
			DEBUG(1, ("%s: ads_get_dn failed\n", __func__));
			continue;
		}

		members[*num_all_members] = dn;
		*num_all_members += 1;
	}

	status = NT_STATUS_OK;
done:
	if (res != NULL) {
		ads_msgfree(ads, res);
	}
	TALLOC_FREE(filter);
	return status;
}