Exemple #1
0
BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
{
	extern pstring global_myname;
	extern fstring global_myworkgroup;
	fstring sid;
	char *sep = lp_winbind_separator();

	*name_type = SID_NAME_UNKNOWN;

	if (!winbind_lookup_name(NULL, name, psid, name_type) || (*name_type != SID_NAME_USER) ) {
		BOOL ret = False;

		DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name));

		/* If we are looking up a domain user, make sure it is
		   for the local machine only */

		if (strchr(name, sep[0]) || strchr(name, '\\')) {
			fstring domain, username;

			split_domain_name(name, domain, username);

			switch (lp_server_role()) {
				case ROLE_DOMAIN_PDC:
				case ROLE_DOMAIN_BDC:
					if (strequal(domain, global_myworkgroup)) {
						fstrcpy(domain, global_myname);
						ret = local_lookup_name(domain, username, psid, name_type);
					}
					/* No break is deliberate here. JRA. */
				default:
					if (strcasecmp(global_myname, domain) != 0) {
						DEBUG(5, ("lookup_name: domain %s is not local\n", domain));
						ret = local_lookup_name(global_myname, username, psid, name_type);
					}
			}
		} else {
			ret = local_lookup_name(global_myname, name, psid, name_type);
		}

		if (ret) {
			DEBUG(10,
			      ("lookup_name: (local) %s -> SID %s (type %u)\n",
			       name, sid_to_string(sid,psid),
			       (unsigned int)*name_type ));
		} else {
			DEBUG(10,("lookup name: (local) %s failed.\n", name));
		}

		return ret;
	}

	DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n",
		  name, sid_to_string(sid, psid), 
		  (unsigned int)*name_type));
	return True;
}
Exemple #2
0
struct sys_userlist *get_users_in_group(const char *gname)
{
	struct sys_userlist *list_head = NULL;
	struct group *gptr;
	fstring domain;
	fstring groupname;
	DOM_SID sid;
	enum SID_NAME_USE name_type;

	/* No point using winbind if we can't split it in the
	   first place */
	if (split_domain_and_name(gname, domain, groupname)) {

		/*
		 * If we're doing this via winbindd, don't do the
		 * entire group list enumeration as we know this is
		 * pointless (and slow).
		 */
		
		if (winbind_lookup_name(domain, groupname, &sid, &name_type) 
		    && name_type == SID_NAME_DOM_GRP) {
			if ((gptr = (struct group *)getgrnam(gname)) == NULL)
				return NULL;
			return add_members_to_userlist(list_head, gptr);
		}
	}
	
#if !defined(BROKEN_GETGRNAM)
	if ((gptr = (struct group *)getgrnam(gname)) == NULL)
		return NULL;
	return add_members_to_userlist(list_head, gptr);
#else
	/* BROKEN_GETGRNAM - True64 */
	setgrent();
	while((gptr = getgrent()) != NULL) {
		if (strequal(gname, gptr->gr_name)) {
			list_head = add_members_to_userlist(list_head, gptr);
			if (list_head == NULL)
				return NULL;
		}
	}
	endgrent();
	return list_head;
#endif
}
Exemple #3
0
bool lookup_name(TALLOC_CTX *mem_ctx,
		 const char *full_name, int flags,
		 const char **ret_domain, const char **ret_name,
		 DOM_SID *ret_sid, enum lsa_SidType *ret_type)
{
	char *p;
	const char *tmp;
	const char *domain = NULL;
	const char *name = NULL;
	uint32 rid;
	DOM_SID sid;
	enum lsa_SidType type;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

	if (tmp_ctx == NULL) {
		DEBUG(0, ("talloc_new failed\n"));
		return false;
	}

	p = strchr_m(full_name, '\\');

	if (p != NULL) {
		domain = talloc_strndup(tmp_ctx, full_name,
					PTR_DIFF(p, full_name));
		name = talloc_strdup(tmp_ctx, p+1);
	} else {
		domain = talloc_strdup(tmp_ctx, "");
		name = talloc_strdup(tmp_ctx, full_name);
	}

	if ((domain == NULL) || (name == NULL)) {
		DEBUG(0, ("talloc failed\n"));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
		full_name, domain, name));
	DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));

	if ((flags & LOOKUP_NAME_DOMAIN) &&
	    strequal(domain, get_global_sam_name()))
	{

		/* It's our own domain, lookup the name in passdb */
		if (lookup_global_sam_name(name, flags, &rid, &type)) {
			sid_copy(&sid, get_global_sam_sid());
			sid_append_rid(&sid, rid);
			goto ok;
		}
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	if ((flags & LOOKUP_NAME_BUILTIN) &&
	    strequal(domain, builtin_domain_name()))
	{
		/* Explicit request for a name in BUILTIN */
		if (lookup_builtin_name(name, &rid)) {
			sid_copy(&sid, &global_sid_Builtin);
			sid_append_rid(&sid, rid);
			type = SID_NAME_ALIAS;
			goto ok;
		}
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	/* Try the explicit winbind lookup first, don't let it guess the
	 * domain yet at this point yet. This comes later. */

	if ((domain[0] != '\0') &&
	    (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
	    (winbind_lookup_name(domain, name, &sid, &type))) {
			goto ok;
	}

	if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_users_domain_name())) {
		if (lookup_unix_user_name(name, &sid)) {
			type = SID_NAME_USER;
			goto ok;
		}
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	if (!(flags & LOOKUP_NAME_EXPLICIT) && strequal(domain, unix_groups_domain_name())) {
		if (lookup_unix_group_name(name, &sid)) {
			type = SID_NAME_DOM_GRP;
			goto ok;
		}
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	/* Now the guesswork begins, we haven't been given an explicit
	 * domain. Try the sequence as documented on
	 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
	 * November 27, 2005 */

	/* 1. well-known names */

	if ((flags & LOOKUP_NAME_WKN) &&
	    lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
	{
		type = SID_NAME_WKN_GRP;
		goto ok;
	}

	/* 2. Builtin domain as such */

	if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
	    strequal(name, builtin_domain_name()))
	{
		/* Swap domain and name */
		tmp = name; name = domain; domain = tmp;
		sid_copy(&sid, &global_sid_Builtin);
		type = SID_NAME_DOMAIN;
		goto ok;
	}

	/* 3. Account domain */

	if ((flags & LOOKUP_NAME_DOMAIN) &&
	    strequal(name, get_global_sam_name()))
	{
		if (!secrets_fetch_domain_sid(name, &sid)) {
			DEBUG(3, ("Could not fetch my SID\n"));
			TALLOC_FREE(tmp_ctx);
			return false;
		}
		/* Swap domain and name */
		tmp = name; name = domain; domain = tmp;
		type = SID_NAME_DOMAIN;
		goto ok;
	}

	/* 4. Primary domain */

	if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
	    strequal(name, lp_workgroup()))
	{
		if (!secrets_fetch_domain_sid(name, &sid)) {
			DEBUG(3, ("Could not fetch the domain SID\n"));
			TALLOC_FREE(tmp_ctx);
			return false;
		}
		/* Swap domain and name */
		tmp = name; name = domain; domain = tmp;
		type = SID_NAME_DOMAIN;
		goto ok;
	}

	/* 5. Trusted domains as such, to me it looks as if members don't do
              this, tested an XP workstation in a NT domain -- vl */

	if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
	    (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
	{
		/* Swap domain and name */
		tmp = name; name = domain; domain = tmp;
		type = SID_NAME_DOMAIN;
		goto ok;
	}

	/* 6. Builtin aliases */	

	if ((flags & LOOKUP_NAME_BUILTIN) &&
	    lookup_builtin_name(name, &rid))
	{
		domain = talloc_strdup(tmp_ctx, builtin_domain_name());
		sid_copy(&sid, &global_sid_Builtin);
		sid_append_rid(&sid, rid);
		type = SID_NAME_ALIAS;
		goto ok;
	}

	/* 7. Local systems' SAM (DCs don't have a local SAM) */
	/* 8. Primary SAM (On members, this is the domain) */

	/* Both cases are done by looking at our passdb */

	if ((flags & LOOKUP_NAME_DOMAIN) &&
	    lookup_global_sam_name(name, flags, &rid, &type))
	{
		domain = talloc_strdup(tmp_ctx, get_global_sam_name());
		sid_copy(&sid, get_global_sam_sid());
		sid_append_rid(&sid, rid);
		goto ok;
	}

	/* Now our local possibilities are exhausted. */

	if (!(flags & LOOKUP_NAME_REMOTE)) {
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	/* If we are not a DC, we have to ask in our primary domain. Let
	 * winbind do that. */

	if (!IS_DC &&
	    (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
		domain = talloc_strdup(tmp_ctx, lp_workgroup());
		goto ok;
	}

	/* 9. Trusted domains */

	/* If we're a DC we have to ask all trusted DC's. Winbind does not do
	 * that (yet), but give it a chance. */

	if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
		DOM_SID dom_sid;
		uint32 tmp_rid;
		enum lsa_SidType domain_type;
		
		if (type == SID_NAME_DOMAIN) {
			/* Swap name and type */
			tmp = name; name = domain; domain = tmp;
			goto ok;
		}

		/* Here we have to cope with a little deficiency in the
		 * winbind API: We have to ask it again for the name of the
		 * domain it figured out itself. Maybe fix that later... */

		sid_copy(&dom_sid, &sid);
		sid_split_rid(&dom_sid, &tmp_rid);

		if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
					&domain_type) ||
		    (domain_type != SID_NAME_DOMAIN)) {
			DEBUG(2, ("winbind could not find the domain's name "
				  "it just looked up for us\n"));
			TALLOC_FREE(tmp_ctx);
			return false;
		}
		goto ok;
	}

	/* 10. Don't translate */

	/* 11. Ok, windows would end here. Samba has two more options:
               Unmapped users and unmapped groups */

	if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_user_name(name, &sid)) {
		domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
		type = SID_NAME_USER;
		goto ok;
	}

	if (!(flags & LOOKUP_NAME_EXPLICIT) && lookup_unix_group_name(name, &sid)) {
		domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
		type = SID_NAME_DOM_GRP;
		goto ok;
	}

	/*
	 * Ok, all possibilities tried. Fail.
	 */

	TALLOC_FREE(tmp_ctx);
	return false;

 ok:
	if ((domain == NULL) || (name == NULL)) {
		DEBUG(0, ("talloc failed\n"));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	/*
	 * Hand over the results to the talloc context we've been given.
	 */

	if ((ret_name != NULL) &&
	    !(*ret_name = talloc_strdup(mem_ctx, name))) {
		DEBUG(0, ("talloc failed\n"));
		TALLOC_FREE(tmp_ctx);
		return false;
	}

	if (ret_domain != NULL) {
		char *tmp_dom;
		if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
			DEBUG(0, ("talloc failed\n"));
			TALLOC_FREE(tmp_ctx);
			return false;
		}
		strupper_m(tmp_dom);
		*ret_domain = tmp_dom;
	}

	if (ret_sid != NULL) {
		sid_copy(ret_sid, &sid);
	}

	if (ret_type != NULL) {
		*ret_type = type;
	}

	TALLOC_FREE(tmp_ctx);
	return true;
}
Exemple #4
0
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
{
	int i;

	/* initialize the status to avoid suprise */
	for (i = 0; ids[i]; i++) {
		ids[i]->status = ID_UNKNOWN;
	}

	for (i = 0; ids[i]; i++) {
		struct passwd *pw;
		struct group *gr;
		const char *name;
		enum lsa_SidType type;
		bool ret;

		switch (ids[i]->xid.type) {
		case ID_TYPE_UID:
			pw = getpwuid((uid_t)ids[i]->xid.id);

			if (!pw) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = pw->pw_name;
			break;
		case ID_TYPE_GID:
			gr = getgrgid((gid_t)ids[i]->xid.id);

			if (!gr) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = gr->gr_name;
			break;
		default: /* ?? */
			ids[i]->status = ID_UNKNOWN;
			continue;
		}

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		(void)winbind_on();
		/* Lookup name from PDC using lsa_lookup_names() */
		ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
		(void)winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER:
			if (ids[i]->xid.type == ID_TYPE_UID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:
			if (ids[i]->xid.type == ID_TYPE_GID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
	}
	return NT_STATUS_OK;
}
Exemple #5
0
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
{
	TALLOC_CTX *ctx;
	int i;

	if (! dom->initialized) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	ctx = talloc_new(dom);
	if ( ! ctx) {
		DEBUG(0, ("Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	for (i = 0; ids[i]; i++) {
		struct passwd *pw;
		struct group *gr;
		const char *name;
		enum lsa_SidType type;
		BOOL ret;
		
		switch (ids[i]->xid.type) {
		case ID_TYPE_UID:
			pw = getpwuid((uid_t)ids[i]->xid.id);

			if (!pw) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = pw->pw_name;
			break;
		case ID_TYPE_GID:
			gr = getgrgid((gid_t)ids[i]->xid.id);

			if (!gr) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = gr->gr_name;
			break;
		default: /* ?? */
			ids[i]->status = ID_UNKNOWN;
			continue;
		}

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		winbind_on();
		/* Lookup name from PDC using lsa_lookup_names() */
		ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
		winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER:
			if (ids[i]->xid.type == ID_TYPE_UID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:
			if (ids[i]->xid.type == ID_TYPE_GID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
	}


	talloc_free(ctx);
	return NT_STATUS_OK;
}