示例#1
0
/*
  join a machine to a realm, creating the machine account
  and setting the machine password
*/
int ads_join_realm(ADS_STRUCT *ads, const char *hostname)
{
	int rc;
	LDAPMessage *res;
	char *principal;

	rc = ads_find_machine_acct(ads, &res, hostname);
	if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1) {
		DEBUG(0, ("Host account for %s already exists\n", hostname));
		goto set_password;
	}

	rc = ads_add_machine_acct(ads, hostname);
	if (rc != LDAP_SUCCESS) {
		DEBUG(0, ("ads_add_machine_acct: %s\n", ads_errstr(rc)));
		return rc;
	}

	rc = ads_find_machine_acct(ads, &res, hostname);
	if (rc != LDAP_SUCCESS || ads_count_replies(ads, res) != 1) {
		DEBUG(0, ("Host account test failed\n"));
		/* hmmm, we need NTSTATUS */
		return -1;
	}

set_password:
	asprintf(&principal, "HOST/%s@%s", hostname, ads->realm);
	krb5_set_principal_password(principal, ads->ldap_server, hostname, ads->realm);
	free(principal);

	return LDAP_SUCCESS;
}
示例#2
0
static int net_ads_status(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	void *res;

	if (!(ads = ads_startup())) {
		return -1;
	}

	rc = ads_find_machine_acct(ads, &res, global_myname());
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}

	if (ads_count_replies(ads, res) == 0) {
		d_printf("No machine account for '%s' found\n", global_myname());
		ads_destroy(&ads);
		return -1;
	}

	ads_dump(ads, res);
	ads_destroy(&ads);
	return 0;
}
示例#3
0
static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
                                       const char *printer)
{
	ADS_STATUS ads_rc;
	LDAPMessage *res = NULL;
	char *prt_dn = NULL;

	DEBUG(5, ("unpublishing printer %s\n", printer));

	/* remove the printer from the directory */
	ads_rc = ads_find_printer_on_server(ads, &res,
					    printer, lp_netbios_name());

	if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
		prt_dn = ads_get_dn(ads, talloc_tos(), res);
		if (!prt_dn) {
			ads_msgfree(ads, res);
			return WERR_NOMEM;
		}
		ads_rc = ads_del_dn(ads, prt_dn);
		TALLOC_FREE(prt_dn);
	}

	if (res) {
		ads_msgfree(ads, res);
	}
	return WERR_OK;
}
示例#4
0
static int net_ads_printer_search(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	void *res = NULL;

	if (!(ads = ads_startup())) {
		return -1;
	}

	rc = ads_find_printers(ads, &res);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_find_printer: %s\n", ads_errstr(rc));
		ads_msgfree(ads, res);
		ads_destroy(&ads);
	 	return -1;
	}

	if (ads_count_replies(ads, res) == 0) {
		d_printf("No results found\n");
		ads_msgfree(ads, res);
		ads_destroy(&ads);
		return -1;
	}

	ads_dump(ads, res);
	ads_msgfree(ads, res);
	ads_destroy(&ads);
	return 0;
}
示例#5
0
static int net_ads_printer_remove(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	const char *servername;
	char *prt_dn;
	void *res = NULL;

	if (!(ads = ads_startup())) {
		return -1;
	}

	if (argc < 1) {
		return net_ads_printer_usage(argc, argv);
	}

	if (argc > 1) {
		servername = argv[1];
	} else {
		servername = global_myname();
	}

	rc = ads_find_printer_on_server(ads, &res, argv[0], servername);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
		ads_msgfree(ads, res);
		ads_destroy(&ads);
		return -1;
	}

	if (ads_count_replies(ads, res) == 0) {
		d_printf("Printer '%s' not found\n", argv[1]);
		ads_msgfree(ads, res);
		ads_destroy(&ads);
		return -1;
	}

	prt_dn = ads_get_dn(ads, res);
	ads_msgfree(ads, res);
	rc = ads_del_dn(ads, prt_dn);
	ads_memfree(ads, prt_dn);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_del_dn: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}

	ads_destroy(&ads);
	return 0;
}
示例#6
0
/*
  find a printer given the name and the hostname
    Note that results "res" may be allocated on return so that the
    results can be used.  It should be freed using ads_msgfree.
*/
 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
				       const char *printer,
				       const char *servername)
{
	ADS_STATUS status;
	char *srv_dn, **srv_cn, *s = NULL;
	const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};

	status = ads_find_machine_acct(ads, res, servername);
	if (!ADS_ERR_OK(status)) {
		DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
			  servername));
		return status;
	}
	if (ads_count_replies(ads, *res) != 1) {
		ads_msgfree(ads, *res);
		*res = NULL;
		return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
	}
	srv_dn = ldap_get_dn(ads->ldap.ld, *res);
	if (srv_dn == NULL) {
		ads_msgfree(ads, *res);
		*res = NULL;
		return ADS_ERROR(LDAP_NO_MEMORY);
	}
	srv_cn = ldap_explode_dn(srv_dn, 1);
	if (srv_cn == NULL) {
		ldap_memfree(srv_dn);
		ads_msgfree(ads, *res);
		*res = NULL;
		return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
	}
	ads_msgfree(ads, *res);
	*res = NULL;

	if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
		ldap_memfree(srv_dn);
		return ADS_ERROR(LDAP_NO_MEMORY);
	}
	status = ads_search(ads, res, s, attrs);

	ldap_memfree(srv_dn);
	ldap_value_free(srv_cn);
	SAFE_FREE(s);
	return status;	
}
示例#7
0
static int net_ads_printer_info(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	const char *servername, *printername;
	void *res = NULL;

	if (!(ads = ads_startup())) {
		return -1;
	}

	if (argc > 0) {
		printername = argv[0];
	} else {
		printername = "*";
	}

	if (argc > 1) {
		servername =  argv[1];
	} else {
		servername = global_myname();
	}

	rc = ads_find_printer_on_server(ads, &res, printername, servername);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
		ads_msgfree(ads, res);
		ads_destroy(&ads);
		return -1;
	}

	if (ads_count_replies(ads, res) == 0) {
		d_printf("Printer '%s' not found\n", printername);
		ads_msgfree(ads, res);
		ads_destroy(&ads);
		return -1;
	}

	ads_dump(ads, res);
	ads_msgfree(ads, res);
	ads_destroy(&ads);

	return 0;
}
示例#8
0
static int ads_group_add(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS status;
	void *res=NULL;
	int rc = -1;

	if (argc < 1) {
		return net_ads_group_usage(argc, argv);
	}
	
	if (!(ads = ads_startup())) {
		return -1;
	}

	status = ads_find_user_acct(ads, &res, argv[0]);

	if (!ADS_ERR_OK(status)) {
		d_printf("ads_group_add: %s\n", ads_errstr(status));
		goto done;
	}
	
	if (ads_count_replies(ads, res)) {
		d_printf("ads_group_add: Group %s already exists\n", argv[0]);
		ads_msgfree(ads, res);
		goto done;
	}

	status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);

	if (ADS_ERR_OK(status)) {
		d_printf("Group %s added\n", argv[0]);
		rc = 0;
	} else {
		d_printf("Could not add group %s: %s\n", argv[0],
			 ads_errstr(status));
	}

 done:
	if (res)
		ads_msgfree(ads, res);
	ads_destroy(&ads);
	return rc;
}
示例#9
0
/*
  general ADS search function. Useful in diagnosing problems in ADS
*/
static int net_ads_dn(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	const char *dn;
	const char **attrs;
	void *res = NULL;

	if (argc < 1) {
		return net_ads_dn_usage(argc, argv);
	}

	if (!(ads = ads_startup())) {
		return -1;
	}

	dn = argv[0];
	attrs = (argv + 1);

	rc = ads_do_search_all(ads, dn, 
			       LDAP_SCOPE_BASE,
			       "(objectclass=*)", attrs, &res);
	if (!ADS_ERR_OK(rc)) {
		d_printf("search failed: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}	

	d_printf("Got %d replies\n\n", ads_count_replies(ads, res));

	/* dump the results */
	ads_dump(ads, res);

	ads_msgfree(ads, res);
	ads_destroy(&ads);

	return 0;
}
示例#10
0
/*
  general ADS search function. Useful in diagnosing problems in ADS
*/
static int net_ads_search(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	const char *ldap_exp;
	const char **attrs;
	void *res = NULL;

	if (argc < 1) {
		return net_ads_search_usage(argc, argv);
	}

	if (!(ads = ads_startup())) {
		return -1;
	}

	ldap_exp = argv[0];
	attrs = (argv + 1);

	rc = ads_do_search_all(ads, ads->config.bind_path,
			       LDAP_SCOPE_SUBTREE,
			       ldap_exp, attrs, &res);
	if (!ADS_ERR_OK(rc)) {
		d_printf("search failed: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}	

	d_printf("Got %d replies\n\n", ads_count_replies(ads, res));

	/* dump the results */
	ads_dump(ads, res);

	ads_msgfree(ads, res);
	ads_destroy(&ads);

	return 0;
}
示例#11
0
 ADS_STATUS cell_do_search(struct likewise_cell *c,
			  const char *search_base,
			  int scope,
			  const char *expr,
			  const char **attrs,
			  LDAPMessage ** msg)
{
	int search_count = 0;
	ADS_STATUS status;
	NTSTATUS nt_status;

	/* check for a NULL connection */

	if (!c->conn) {
		nt_status = cell_connect(c);
		if (!NT_STATUS_IS_OK(nt_status)) {
			status = ADS_ERROR_NT(nt_status);
			return status;
		}
	}

	DEBUG(10, ("cell_do_search: Base = %s,  Filter = %s, Scope = %d, GC = %s\n",
		   search_base, expr, scope,
		   c->conn->server.gc ? "yes" : "no"));

	/* we try multiple times in case the ADS_STRUCT is bad
	   and we need to reconnect */

	while (search_count < MAX_SEARCH_COUNT) {
		*msg = NULL;
		status = ads_do_search(c->conn, search_base,
				       scope, expr, attrs, msg);
		if (ADS_ERR_OK(status)) {
			if (DEBUGLEVEL >= 10) {
				LDAPMessage *e = NULL;

				int n = ads_count_replies(c->conn, *msg);

				DEBUG(10,("cell_do_search: Located %d entries\n", n));

				for (e=ads_first_entry(c->conn, *msg);
				     e!=NULL;
				     e = ads_next_entry(c->conn, e))
				{
					char *dn = ads_get_dn(c->conn, talloc_tos(), e);

					DEBUGADD(10,("   dn: %s\n", dn ? dn : "<NULL>"));
					TALLOC_FREE(dn);
				}
			}

			return status;
		}


		DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n",
			  search_count, ads_errstr(status)));

		search_count++;

		/* Houston, we have a problem */

		if (status.error_type == ENUM_ADS_ERROR_LDAP) {
			switch (status.err.rc) {
			case LDAP_TIMELIMIT_EXCEEDED:
			case LDAP_TIMEOUT:
			case -1:	/* we get this error if we cannot contact
					   the LDAP server */
				nt_status = cell_connect(c);
				if (!NT_STATUS_IS_OK(nt_status)) {
					status = ADS_ERROR_NT(nt_status);
					return status;
				}
				break;
			default:
				/* we're all done here */
				return status;
			}
		}
	}

	DEBUG(5, ("cell_do_search: exceeded maximum search count!\n"));

	return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
示例#12
0
static int ads_user_add(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS status;
	char *upn, *userdn;
	void *res=NULL;
	int rc = -1;

	if (argc < 1) return net_ads_user_usage(argc, argv);
	
	if (!(ads = ads_startup())) {
		return -1;
	}

	status = ads_find_user_acct(ads, &res, argv[0]);

	if (!ADS_ERR_OK(status)) {
		d_printf("ads_user_add: %s\n", ads_errstr(status));
		goto done;
	}
	
	if (ads_count_replies(ads, res)) {
		d_printf("ads_user_add: User %s already exists\n", argv[0]);
		goto done;
	}

	status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);

	if (!ADS_ERR_OK(status)) {
		d_printf("Could not add user %s: %s\n", argv[0],
			 ads_errstr(status));
		goto done;
	}

	/* if no password is to be set, we're done */
	if (argc == 1) { 
		d_printf("User %s added\n", argv[0]);
		rc = 0;
		goto done;
	}

	/* try setting the password */
	asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
	status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1], 
				       ads->auth.time_offset);
	safe_free(upn);
	if (ADS_ERR_OK(status)) {
		d_printf("User %s added\n", argv[0]);
		rc = 0;
		goto done;
	}

	/* password didn't set, delete account */
	d_printf("Could not add user %s.  Error setting password %s\n",
		 argv[0], ads_errstr(status));
	ads_msgfree(ads, res);
	status=ads_find_user_acct(ads, &res, argv[0]);
	if (ADS_ERR_OK(status)) {
		userdn = ads_get_dn(ads, res);
		ads_del_dn(ads, userdn);
		ads_memfree(ads, userdn);
	}

 done:
	if (res)
		ads_msgfree(ads, res);
	ads_destroy(&ads);
	return rc;
}
示例#13
0
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
			       TALLOC_CTX *mem_ctx,
			       uint32 *num_entries, 
			       struct wbint_userinfo **info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "*", NULL };
	int i, count;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;

	*num_entries = 0;

	DEBUG(3,("ads: query_user_list\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("query_user_list: No users found\n"));
		goto done;
	}

	(*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct wbint_userinfo, count);
	if (!*info) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	i = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		const char *name;
		const char *gecos = NULL;
		const char *homedir = NULL;
		const char *shell = NULL;
		uint32 group;
		uint32 atype;
		DOM_SID user_sid;
		gid_t primary_gid = (gid_t)-1;

		if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
		    ds_atype_map(atype) != SID_NAME_USER) {
			DEBUG(1,("Not a user account? atype=0x%x\n", atype));
			continue;
		}

		name = ads_pull_username(ads, mem_ctx, msg);

		if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
			status = nss_get_info_cached( domain, &user_sid, mem_ctx, 
					       ads, msg, &homedir, &shell, &gecos,
					       &primary_gid );
		}

		if (gecos == NULL) {
			gecos = ads_pull_string(ads, mem_ctx, msg, "name");
		}

		if (!ads_pull_sid(ads, msg, "objectSid",
				  &(*info)[i].user_sid)) {
			DEBUG(1,("No sid for %s !?\n", name));
			continue;
		}
		if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
			DEBUG(1,("No primary group for %s !?\n", name));
			continue;
		}

		(*info)[i].acct_name = name;
		(*info)[i].full_name = gecos;
		(*info)[i].homedir = homedir;
		(*info)[i].shell = shell;
		(*info)[i].primary_gid = primary_gid;
		sid_compose(&(*info)[i].group_sid, &domain->sid, group);
		i++;
	}

	(*num_entries) = i;
	status = NT_STATUS_OK;

	DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));

done:
	if (res) 
		ads_msgfree(ads, res);

	return status;
}
示例#14
0
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
				  TALLOC_CTX *mem_ctx,
				  const struct dom_sid *sid,
				  uint32 *p_num_groups, struct dom_sid **user_sids)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
	ADS_STATUS rc;
	int count;
	LDAPMessage *msg = NULL;
	char *user_dn = NULL;
	struct dom_sid *sids;
	int i;
	struct dom_sid primary_group;
	uint32 primary_group_rid;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	uint32_t num_groups = 0;

	DEBUG(3,("ads: lookup_usergroups\n"));
	*p_num_groups = 0;

	status = lookup_usergroups_cached(domain, mem_ctx, sid, 
					  p_num_groups, user_sids);
	if (NT_STATUS_IS_OK(status)) {
		return NT_STATUS_OK;
	}

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
			  domain->name));

		/* Tell the cache manager not to remember this one */

		return NT_STATUS_SYNCHRONIZATION_REQUIRED;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry_sid(ads, &msg, sid, attrs);

	if (!ADS_ERR_OK(rc)) {
		status = ads_ntstatus(rc);
		DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
			  "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, msg);
	if (count != 1) {
		status = NT_STATUS_UNSUCCESSFUL;
		DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
			 "invalid number of results (count=%d)\n", 
			 sid_string_dbg(sid), count));
		goto done;
	}

	if (!msg) {
		DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n", 
			 sid_string_dbg(sid)));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	user_dn = ads_get_dn(ads, mem_ctx, msg);
	if (user_dn == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
		DEBUG(1,("%s: No primary group for sid=%s !?\n", 
			 domain->name, sid_string_dbg(sid)));
		goto done;
	}

	sid_compose(&primary_group, &domain->sid, primary_group_rid);

	count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);

	/* there must always be at least one group in the token, 
	   unless we are talking to a buggy Win2k server */

	/* actually this only happens when the machine account has no read
	 * permissions on the tokenGroup attribute - gd */

	if (count == 0) {

		/* no tokenGroups */

		/* lookup what groups this user is a member of by DN search on
		 * "memberOf" */

		status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
						    &primary_group,
						    &num_groups, user_sids);
		*p_num_groups = num_groups;
		if (NT_STATUS_IS_OK(status)) {
			goto done;
		}

		/* lookup what groups this user is a member of by DN search on
		 * "member" */

		status = lookup_usergroups_member(domain, mem_ctx, user_dn, 
						  &primary_group,
						  &num_groups, user_sids);
		*p_num_groups = num_groups;
		goto done;
	}

	*user_sids = NULL;
	num_groups = 0;

	status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
				  &num_groups);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	for (i=0;i<count;i++) {

		/* ignore Builtin groups from ADS - Guenther */
		if (sid_check_is_in_builtin(&sids[i])) {
			continue;
		}

		status = add_sid_to_array_unique(mem_ctx, &sids[i],
						 user_sids, &num_groups);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}
	}

	*p_num_groups = (uint32)num_groups;
	status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;

	DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
		 sid_string_dbg(sid)));
done:
	TALLOC_FREE(user_dn);
	ads_msgfree(ads, msg);
	return status;
}
示例#15
0
/*
  a wrapper around ldap_search_s that retries depending on the error code
  this is supposed to catch dropped connections and auto-reconnect
*/
ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope, 
			       const char *expr,
			       const char **attrs, void **res)
{
	ADS_STATUS status;
	int count = 3;
	char *bp;

	*res = NULL;

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

	bp = strdup(bind_path);

	if (!bp) {
		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
	}

	while (count--) {
		*res = NULL;
		status = ads_do_search_all(ads, bp, scope, expr, attrs, res);
		if (ADS_ERR_OK(status)) {
			DEBUG(5,("Search for %s gave %d replies\n",
				 expr, ads_count_replies(ads, *res)));
			SAFE_FREE(bp);
			return status;
		}

		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)));
			 
		if (ads->ld) {
			ldap_unbind(ads->ld); 
		}
		
		ads->ld = NULL;
		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;
		}
	}
        SAFE_FREE(bp);

	if (!ADS_ERR_OK(status))
		DEBUG(1,("ads reopen failed after error %s\n", 
			 ads_errstr(status)));

	return status;
}
示例#16
0
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, 
			   TALLOC_CTX *mem_ctx, 
			   const struct dom_sid *sid,
			   struct wbint_userinfo *info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "*", NULL };
	ADS_STATUS rc;
	int count;
	LDAPMessage *msg = NULL;
	char *ldap_exp;
	char *sidstr;
	uint32 group_rid;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	struct netr_SamInfo3 *user = NULL;
	gid_t gid = -1;
	int ret;
	char *ads_name;

	DEBUG(3,("ads: query_user\n"));

	info->homedir = NULL;
	info->shell = NULL;

	/* try netsamlogon cache first */

	if (winbindd_use_cache() && (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
	{
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			 sid_string_dbg(sid)));

		sid_compose(&info->user_sid, &domain->sid, user->base.rid);
		sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);

		info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
		info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);

		nss_get_info_cached( domain, sid, mem_ctx,
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid );
		info->primary_gid = gid;

		TALLOC_FREE(user);

		return NT_STATUS_OK;
	}

	if ( !winbindd_can_contact_domain(domain)) {
		DEBUG(8,("query_user: No incoming trust from domain %s\n",
			 domain->name));

		/* We still need to generate some basic information
		   about the user even if we cannot contact the 
		   domain.  Most of this stuff we can deduce. */

		sid_copy( &info->user_sid, sid );

		/* Assume "Domain Users" for the primary group */

		sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );

		/* Try to fill in what the nss_info backend can do */

		nss_get_info_cached( domain, sid, mem_ctx,
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid);
		info->primary_gid = gid;

		return NT_STATUS_OK;
	}

	/* no cache...do the query */

	if ( (ads = ads_cached_connection(domain)) == NULL ) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		return NT_STATUS_SERVER_DISABLED;
	}

	sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);

	ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
	TALLOC_FREE(sidstr);
	if (ret == -1) {
		return NT_STATUS_NO_MEMORY;
	}
	rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
	SAFE_FREE(ldap_exp);
	if (!ADS_ERR_OK(rc) || !msg) {
		DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
			 sid_string_dbg(sid), ads_errstr(rc)));
		return ads_ntstatus(rc);
	}

	count = ads_count_replies(ads, msg);
	if (count != 1) {
		DEBUG(1,("query_user(sid=%s): Not found\n",
			 sid_string_dbg(sid)));
		ads_msgfree(ads, msg);
		return NT_STATUS_NO_SUCH_USER;
	}

	info->acct_name = ads_pull_username(ads, mem_ctx, msg);

	if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
		DEBUG(1,("No primary group for %s !?\n",
			 sid_string_dbg(sid)));
		ads_msgfree(ads, msg);
		return NT_STATUS_NO_SUCH_USER;
	}
	sid_copy(&info->user_sid, sid);
	sid_compose(&info->group_sid, &domain->sid, group_rid);

	/*
	 * We have to fetch the "name" attribute before doing the
	 * nss_get_info_cached call. nss_get_info_cached might destroy
	 * the ads struct, potentially invalidating the ldap message.
	 */
	ads_name = ads_pull_string(ads, mem_ctx, msg, "name");

	ads_msgfree(ads, msg);
	msg = NULL;

	status = nss_get_info_cached( domain, sid, mem_ctx,
		      &info->homedir, &info->shell, &info->full_name, 
		      &gid);
	info->primary_gid = gid;
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("nss_get_info_cached failed: %s\n",
			  nt_errstr(status)));
		return status;
	}

	if (info->full_name == NULL) {
		info->full_name = ads_name;
	} else {
		TALLOC_FREE(ads_name);
	}

	status = NT_STATUS_OK;

	DEBUG(3,("ads query_user gave %s\n", info->acct_name));
	return NT_STATUS_OK;
}
示例#17
0
/* Lookup groups a user is a member of - alternate method, for when
   tokenGroups are not available. */
static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
					 TALLOC_CTX *mem_ctx,
					 const char *user_dn, 
					 struct dom_sid *primary_group,
					 uint32_t *p_num_groups, struct dom_sid **user_sids)
{
	ADS_STATUS rc;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	int count;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	char *ldap_exp;
	ADS_STRUCT *ads;
	const char *group_attrs[] = {"objectSid", NULL};
	char *escaped_dn;
	uint32_t num_groups = 0;

	DEBUG(3,("ads: lookup_usergroups_member\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ldap_exp = talloc_asprintf(mem_ctx,
		"(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
		escaped_dn,
		ADS_LDAP_MATCHING_RULE_BIT_AND,
		GROUP_TYPE_SECURITY_ENABLED);
	if (!ldap_exp) {
		DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
		TALLOC_FREE(escaped_dn);
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	TALLOC_FREE(escaped_dn);

	rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);

	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
		return ads_ntstatus(rc);
	}

	count = ads_count_replies(ads, res);

	*user_sids = NULL;
	num_groups = 0;

	/* always add the primary group to the sid array */
	status = add_sid_to_array(mem_ctx, primary_group, user_sids,
				  &num_groups);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	if (count > 0) {
		for (msg = ads_first_entry(ads, res); msg;
		     msg = ads_next_entry(ads, msg)) {
			struct dom_sid group_sid;

			if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
				DEBUG(1,("No sid for this group ?!?\n"));
				continue;
			}

			/* ignore Builtin groups from ADS - Guenther */
			if (sid_check_is_in_builtin(&group_sid)) {
				continue;
			}

			status = add_sid_to_array(mem_ctx, &group_sid,
						  user_sids, &num_groups);
			if (!NT_STATUS_IS_OK(status)) {
				goto done;
			}
		}

	}

	*p_num_groups = num_groups;
	status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;

	DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
done:
	if (res) 
		ads_msgfree(ads, res);

	return status;
}
示例#18
0
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
			       TALLOC_CTX *mem_ctx,
			       uint32_t **prids)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "sAMAccountType", "objectSid", NULL };
	int count;
	uint32_t *rids = NULL;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;

	DEBUG(3,("ads: query_user_list\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
	if (!ADS_ERR_OK(rc)) {
		DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
		status = ads_ntstatus(rc);
		goto done;
	} else if (!res) {
		DEBUG(1,("query_user_list ads_search returned NULL res\n"));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("query_user_list: No users found\n"));
		goto done;
	}

	rids = talloc_zero_array(mem_ctx, uint32_t, count);
	if (rids == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	count = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		struct dom_sid user_sid;
		uint32_t atype;
		bool ok;

		ok = ads_pull_uint32(ads, msg, "sAMAccountType", &atype);
		if (!ok) {
			DBG_INFO("Object lacks sAMAccountType attribute\n");
			continue;
		}
		if (ds_atype_map(atype) != SID_NAME_USER) {
			DBG_INFO("Not a user account? atype=0x%x\n", atype);
			continue;
		}

		if (!ads_pull_sid(ads, msg, "objectSid", &user_sid)) {
			char *dn = ads_get_dn(ads, talloc_tos(), msg);
			DBG_INFO("No sid for %s !?\n", dn);
			TALLOC_FREE(dn);
			continue;
		}

		if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
			fstring sidstr, domstr;
			DBG_WARNING("Got sid %s in domain %s\n",
				    sid_to_fstring(sidstr, &user_sid),
				    sid_to_fstring(domstr, &domain->sid));
			continue;
		}

		sid_split_rid(&user_sid, &rids[count]);
		count += 1;
	}

	rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
	if (prids != NULL) {
		*prids = rids;
	}

	status = NT_STATUS_OK;

	DBG_NOTICE("ads query_user_list gave %d entries\n", count);

done:
	return status;
}
示例#19
0
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, 
			   TALLOC_CTX *mem_ctx, 
			   const DOM_SID *sid, 
			   struct wbint_userinfo *info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "*", NULL };
	ADS_STATUS rc;
	int count;
	LDAPMessage *msg = NULL;
	char *ldap_exp;
	char *sidstr;
	uint32 group_rid;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	struct netr_SamInfo3 *user = NULL;
	gid_t gid;

	DEBUG(3,("ads: query_user\n"));

	info->homedir = NULL;
	info->shell = NULL;
	info->primary_gid = (gid_t)-1;

	/* try netsamlogon cache first */

	if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL ) 
	{
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			 sid_string_dbg(sid)));

		sid_compose(&info->user_sid, &domain->sid, user->base.rid);
		sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);

		info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
		info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);

		nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, 
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid );
		info->primary_gid = gid;

		TALLOC_FREE(user);

		return NT_STATUS_OK;
	}

	if ( !winbindd_can_contact_domain(domain)) {
		DEBUG(8,("query_user: No incoming trust from domain %s\n",
			 domain->name));

		/* We still need to generate some basic information
		   about the user even if we cannot contact the 
		   domain.  Most of this stuff we can deduce. */

		sid_copy( &info->user_sid, sid );

		/* Assume "Domain Users" for the primary group */

		sid_compose(&info->group_sid, &domain->sid, DOMAIN_GROUP_RID_USERS );

		/* Try to fill in what the nss_info backend can do */

		nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, 
			      &info->homedir, &info->shell, &info->full_name, 
			      &gid);
		info->primary_gid = gid;

		status = NT_STATUS_OK;
		goto done;
	}

	/* no cache...do the query */

	if ( (ads = ads_cached_connection(domain)) == NULL ) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	sidstr = sid_binstring(talloc_tos(), sid);
	if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
	free(ldap_exp);
	TALLOC_FREE(sidstr);
	if (!ADS_ERR_OK(rc) || !msg) {
		DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
			 sid_string_dbg(sid), ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, msg);
	if (count != 1) {
		DEBUG(1,("query_user(sid=%s): Not found\n",
			 sid_string_dbg(sid)));
		goto done;
	}

	info->acct_name = ads_pull_username(ads, mem_ctx, msg);

	nss_get_info_cached( domain, sid, mem_ctx, ads, msg, 
		      &info->homedir, &info->shell, &info->full_name, 
		      &gid);
	info->primary_gid = gid;

	if (info->full_name == NULL) {
		info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
	}

	if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
		DEBUG(1,("No primary group for %s !?\n",
			 sid_string_dbg(sid)));
		goto done;
	}

	sid_copy(&info->user_sid, sid);
	sid_compose(&info->group_sid, &domain->sid, group_rid);

	status = NT_STATUS_OK;

	DEBUG(3,("ads query_user gave %s\n", info->acct_name));
done:
	if (msg) 
		ads_msgfree(ads, msg);

	return status;
}
示例#20
0
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;
}
示例#21
0
/* convert a single name to a sid in a domain */
NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
			 const char *name,
			 DOM_SID *sid,
			 enum SID_NAME_USE *type)
{
	const char *attrs[] = {"objectSid", "sAMAccountType", NULL};
	int count;
	ADS_STATUS rc;
	void *res = NULL;
	char *ldap_exp;
	uint32 t;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	char *escaped_name = escape_ldap_string_alloc(name);
	char *escaped_realm = escape_ldap_string_alloc(ads->config.realm);

	if (!escaped_name || !escaped_realm) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", 
		     escaped_name, escaped_name, escaped_realm) == -1) {
		DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	rc = ads_search_retry(ads, &res, ldap_exp, attrs);
	free(ldap_exp);
	if (!ADS_ERR_OK(rc)) {
		DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count != 1) {
		DEBUG(1,("name_to_sid: %s not found\n", name));
		goto done;
	}

	if (!ads_pull_sid(ads, res, "objectSid", sid)) {
		DEBUG(1,("No sid for %s !?\n", name));
		goto done;
	}

	if (!ads_pull_uint32(ads, res, "sAMAccountType", &t)) {
		DEBUG(1,("No sAMAccountType for %s !?\n", name));
		goto done;
	}

	*type = ads_atype_map(t);

	status = NT_STATUS_OK;

	DEBUG(3,("ads name_to_sid mapped %s\n", name));

done:
	if (res) ads_msgfree(ads, res);

	SAFE_FREE(escaped_name);
	SAFE_FREE(escaped_realm);

	return status;
}
示例#22
0
ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads,
			 TALLOC_CTX *mem_ctx,
			 const DOM_SID *sid,
			 char **dn)
{
	ADS_STATUS rc;
	LDAPMessage *msg = NULL;
	LDAPMessage *entry = NULL;
	char *ldap_exp;
	char *sidstr = NULL;
	int count;
	char *dn2 = NULL;

	const char *attr[] = {
		"dn",
		NULL
	};

	if (!(sidstr = sid_binstring(sid))) {
		DEBUG(1,("ads_sid_to_dn: sid_binstring failed!\n"));
		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto done;
	}

	if(!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr))) {
		DEBUG(1,("ads_sid_to_dn: talloc_asprintf failed!\n"));
		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto done;
	}

	rc = ads_search_retry(ads, (void **)&msg, ldap_exp, attr);

	if (!ADS_ERR_OK(rc)) {
		DEBUG(1,("ads_sid_to_dn ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	if ((count = ads_count_replies(ads, msg)) != 1) {
		fstring sid_string;
		DEBUG(1,("ads_sid_to_dn (sid=%s): Not found (count=%d)\n", 
			 sid_to_string(sid_string, sid), count));
		rc = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
		goto done;
	}

	entry = ads_first_entry(ads, msg);

	dn2 = ads_get_dn(ads, entry);

	if (!dn2) {
		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto done;
	}

	*dn = talloc_strdup(mem_ctx, dn2);

	if (!*dn) {
		ads_memfree(ads, dn2);
		rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto done;
	}

	rc = ADS_ERROR_NT(NT_STATUS_OK);

	DEBUG(3,("ads sid_to_dn mapped %s\n", dn2));

	SAFE_FREE(dn2);
done:
	if (msg) ads_msgfree(ads, msg);
	if (dn2) ads_memfree(ads, dn2);

	SAFE_FREE(sidstr);

	return rc;
}
示例#23
0
/*
  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;
}
示例#24
0
static ADS_STATUS ads_ranged_search_internal(ADS_STRUCT *ads,
				      TALLOC_CTX *mem_ctx,
				      int scope,
				      const char *base,
				      const char *filter,
				      const char **attrs,
				      void *args,
				      const char *range_attr,
				      char ***strings,
				      size_t *num_strings,
				      uint32_t *first_usn,
				      int *num_retries,
				      bool *more_values)
{
	LDAPMessage *res = NULL;
	ADS_STATUS status;
	int count;
	uint32_t current_usn;

	DEBUG(10, ("Searching for attrs[0] = %s, attrs[1] = %s\n", attrs[0], attrs[1]));

	*more_values = False;

	status = ads_do_search_retry_internal(ads, base, scope, filter, attrs, args, &res);

	if (!ADS_ERR_OK(status)) {
		DEBUG(1,("ads_search: %s\n",
			 ads_errstr(status)));
		return status;
	}

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

	count = ads_count_replies(ads, res);
	if (count == 0) {
		ads_msgfree(ads, res);
		return ADS_ERROR(LDAP_SUCCESS);
	}

	if (*num_strings == 0) {
		if (!ads_pull_uint32(ads, res, "usnChanged", first_usn)) {
			DEBUG(1, ("could not pull first usnChanged!\n"));
			ads_msgfree(ads, res);
			return ADS_ERROR(LDAP_NO_MEMORY);
		}
	}

	if (!ads_pull_uint32(ads, res, "usnChanged", &current_usn)) {
		DEBUG(1, ("could not pull current usnChanged!\n"));
		ads_msgfree(ads, res);
		return ADS_ERROR(LDAP_NO_MEMORY);
	}

	if (*first_usn != current_usn) {
		DEBUG(5, ("USN on this record changed"
			  " - restarting search\n"));
		if (*num_retries < 5) {
			(*num_retries)++;
			*num_strings = 0;
			ads_msgfree(ads, res);
			return ADS_ERROR_NT(STATUS_MORE_ENTRIES);
		} else {
			DEBUG(5, ("USN on this record changed"
				  " - restarted search too many times, aborting!\n"));
			ads_msgfree(ads, res);
			return ADS_ERROR(LDAP_NO_MEMORY);
		}
	}

	*strings = ads_pull_strings_range(ads, mem_ctx, res,
					 range_attr,
					 *strings,
					 &attrs[0],
					 num_strings,
					 more_values);

	ads_msgfree(ads, res);

	/* paranoia checks */
	if (*strings == NULL && *more_values) {
		DEBUG(0,("no strings found but more values???\n"));
		return ADS_ERROR(LDAP_NO_MEMORY);
	}
	if (*num_strings == 0 && *more_values) {
		DEBUG(0,("no strings found but more values???\n"));
		return ADS_ERROR(LDAP_NO_MEMORY);
	}

	return (*more_values) ? ADS_ERROR_NT(STATUS_MORE_ENTRIES) : ADS_ERROR(LDAP_SUCCESS);
}
示例#25
0
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
			       TALLOC_CTX *mem_ctx,
			       uint32 *num_entries, 
			       struct wbint_userinfo **pinfo)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = { "*", NULL };
	int i, count;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;

	*num_entries = 0;

	DEBUG(3,("ads: query_user_list\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("query_user_list: No users found\n"));
		goto done;
	}

	(*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
	if (!*pinfo) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	count = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		struct wbint_userinfo *info = &((*pinfo)[count]);
		uint32 group;
		uint32 atype;

		if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
		    ds_atype_map(atype) != SID_NAME_USER) {
			DEBUG(1,("Not a user account? atype=0x%x\n", atype));
			continue;
		}

		info->acct_name = ads_pull_username(ads, mem_ctx, msg);
		info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
		info->homedir = NULL;
		info->shell = NULL;
		info->primary_gid = (gid_t)-1;

		if (!ads_pull_sid(ads, msg, "objectSid",
				  &info->user_sid)) {
			DEBUG(1, ("No sid for %s !?\n", info->acct_name));
			continue;
		}

		if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
			DEBUG(1, ("No primary group for %s !?\n",
				  info->acct_name));
			continue;
		}
		sid_compose(&info->group_sid, &domain->sid, group);

		count += 1;
	}

	(*num_entries) = count;
	ads_msgfree(ads, res);

	for (i=0; i<count; i++) {
		struct wbint_userinfo *info = &((*pinfo)[i]);
		const char *gecos = NULL;
		gid_t primary_gid = (gid_t)-1;

		status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
					     &info->homedir, &info->shell,
					     &gecos, &primary_gid);
		if (!NT_STATUS_IS_OK(status)) {
			/*
			 * Deliberately ignore this error, there might be more
			 * users to fill
			 */
			continue;
		}

		if (gecos != NULL) {
			info->full_name = gecos;
		}
		info->primary_gid = primary_gid;
	}

	status = NT_STATUS_OK;

	DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));

done:
	return status;
}
示例#26
0
/* list all domain groups */
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
				TALLOC_CTX *mem_ctx,
				uint32 *num_entries, 
				struct wb_acct_info **info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = {"userPrincipalName", "sAMAccountName",
			       "name", "objectSid", NULL};
	int i, count;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	const char *filter;
	bool enum_dom_local_groups = False;

	*num_entries = 0;

	DEBUG(3,("ads: enum_dom_groups\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	/* only grab domain local groups for our domain */
	if ( domain->active_directory && strequal(lp_realm(), domain->alt_name)  ) {
		enum_dom_local_groups = True;
	}

	/* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
	 * rollup-fixes:
	 *
	 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
	 * default value, it MUST be absent. In case of extensible matching the
	 * "dnattr" boolean defaults to FALSE and so it must be only be present
	 * when set to TRUE. 
	 *
	 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
	 * filter using bitwise matching rule then the buggy AD fails to decode
	 * the extensible match. As a workaround set it to TRUE and thereby add
	 * the dnAttributes "dn" field to cope with those older AD versions.
	 * It should not harm and won't put any additional load on the AD since
	 * none of the dn components have a bitmask-attribute.
	 *
	 * Thanks to Ralf Haferkamp for input and testing - Guenther */

	filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))", 
				 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
				 ADS_LDAP_MATCHING_RULE_BIT_AND, 
				 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);

	if (filter == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, filter, attrs);
	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("enum_dom_groups: No groups found\n"));
		goto done;
	}

	(*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
	if (!*info) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	i = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		char *name, *gecos;
		struct dom_sid sid;
		uint32 rid;

		name = ads_pull_username(ads, mem_ctx, msg);
		gecos = ads_pull_string(ads, mem_ctx, msg, "name");
		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
			DEBUG(1,("No sid for %s !?\n", name));
			continue;
		}

		if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
			DEBUG(1,("No rid for %s !?\n", name));
			continue;
		}

		fstrcpy((*info)[i].acct_name, name);
		fstrcpy((*info)[i].acct_desc, gecos);
		(*info)[i].rid = rid;
		i++;
	}

	(*num_entries) = i;

	status = NT_STATUS_OK;

	DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));

done:
	if (res) 
		ads_msgfree(ads, res);

	return status;
}
示例#27
0
static int net_ads_printer_publish(int argc, const char **argv)
{
        ADS_STRUCT *ads;
        ADS_STATUS rc;
	const char *servername, *printername;
	struct cli_state *cli;
	struct in_addr 		server_ip;
	NTSTATUS nt_status;
	TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
	ADS_MODLIST mods = ads_init_mods(mem_ctx);
	char *prt_dn, *srv_dn, **srv_cn;
	void *res = NULL;

	if (!(ads = ads_startup())) {
		return -1;
	}

	if (argc < 1) {
		return net_ads_printer_usage(argc, argv);
	}
	
	printername = argv[0];

	if (argc == 2) {
		servername = argv[1];
	} else {
		servername = global_myname();
	}
		
	/* Get printer data from SPOOLSS */

	resolve_name(servername, &server_ip, 0x20);

	nt_status = cli_full_connection(&cli, global_myname(), servername, 
					&server_ip, 0,
					"IPC$", "IPC",  
					opt_user_name, opt_workgroup,
					opt_password ? opt_password : "", 
					CLI_FULL_CONNECTION_USE_KERBEROS, 
					Undefined, NULL);

	if (NT_STATUS_IS_ERR(nt_status)) {
		d_printf("Unable to open a connnection to %s to obtain data "
			 "for %s\n", servername, printername);
		ads_destroy(&ads);
		return -1;
	}

	/* Publish on AD server */

	ads_find_machine_acct(ads, &res, servername);

	if (ads_count_replies(ads, res) == 0) {
		d_printf("Could not find machine account for server %s\n", 
			 servername);
		ads_destroy(&ads);
		return -1;
	}

	srv_dn = ldap_get_dn(ads->ld, res);
	srv_cn = ldap_explode_dn(srv_dn, 1);

	asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);

	cli_nt_session_open(cli, PI_SPOOLSS);
	get_remote_printer_publishing_data(cli, mem_ctx, &mods, printername);

        rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
        if (!ADS_ERR_OK(rc)) {
                d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
                return -1;
        }
 
        d_printf("published printer\n");
	ads_destroy(&ads);
 
	return 0;
}
示例#28
0
static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS status;
	LDAPMessage *res = NULL;
	int num_reply = 0;
	LDAPMessage *msg = NULL;
	struct GROUP_POLICY_OBJECT gpo;
	TALLOC_CTX *mem_ctx;
	char *dn;
	const char *attrs[] = {
		"versionNumber",
		"flags",
		"gPCFileSysPath",
		"displayName",
		"name",
		"gPCMachineExtensionNames",
		"gPCUserExtensionNames",
		"ntSecurityDescriptor",
		NULL
	};

	if (c->display_usage) {
		d_printf("Usage:\n"
			 "net ads gpo listall\n"
			 "    List all GPOs on the DC\n");
		return 0;
	}

	mem_ctx = talloc_init("net_ads_gpo_list_all");
	if (mem_ctx == NULL) {
		return -1;
	}

	status = ads_startup(c, false, &ads);
	if (!ADS_ERR_OK(status)) {
		goto out;
	}

	status = ads_do_search_all_sd_flags(ads, ads->config.bind_path,
					    LDAP_SCOPE_SUBTREE,
					    "(objectclass=groupPolicyContainer)",
					    attrs,
					    DACL_SECURITY_INFORMATION,
					    &res);

	if (!ADS_ERR_OK(status)) {
		d_printf("search failed: %s\n", ads_errstr(status));
		goto out;
	}

	num_reply = ads_count_replies(ads, res);

	d_printf("Got %d replies\n\n", num_reply);

	/* dump the results */
	for (msg = ads_first_entry(ads, res);
	     msg;
	     msg = ads_next_entry(ads, msg)) {

		if ((dn = ads_get_dn(ads, mem_ctx, msg)) == NULL) {
			goto out;
		}

		status = ads_parse_gpo(ads, mem_ctx, msg, dn, &gpo);

		if (!ADS_ERR_OK(status)) {
			d_printf("ads_parse_gpo failed: %s\n",
				ads_errstr(status));
			goto out;
		}

		dump_gpo(ads, mem_ctx, &gpo, 0);
	}

out:
	ads_msgfree(ads, res);

	TALLOC_FREE(mem_ctx);
	ads_destroy(&ads);

	return 0;
}