예제 #1
0
static bool token_contains_name(TALLOC_CTX *mem_ctx,
				const char *username,
				const char *domain,
				const char *sharename,
				const struct nt_user_token *token,
				const char *name)
{
	const char *prefix;
	DOM_SID sid;
	enum lsa_SidType type;
	struct smbd_server_connection *sconn = smbd_server_conn;

	if (username != NULL) {
		name = talloc_sub_basic(mem_ctx, username, domain, name);
	}
	if (sharename != NULL) {
		name = talloc_string_sub(mem_ctx, name, "%S", sharename);
	}

	if (name == NULL) {
		/* This is too security sensitive, better panic than return a
		 * result that might be interpreted in a wrong way. */
		smb_panic("substitutions failed");
	}
	
	/* check to see is we already have a SID */

	if ( string_to_sid( &sid, name ) ) {
		DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name));
		return nt_token_check_sid( &sid, token );
	}

	if (!do_group_checks(&name, &prefix)) {
		if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL,
				 NULL, NULL, &sid, &type)) {
			DEBUG(5, ("lookup_name %s failed\n", name));
			return False;
		}
		if (type != SID_NAME_USER) {
			DEBUG(5, ("%s is a %s, expected a user\n",
				  name, sid_type_lookup(type)));
			return False;
		}
		return nt_token_check_sid(&sid, token);
	}

	for (/* initialized above */ ; *prefix != '\0'; prefix++) {
		if (*prefix == '+') {
			if (!lookup_name_smbconf(mem_ctx, name,
					 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
					 NULL, NULL, &sid, &type)) {
				DEBUG(5, ("lookup_name %s failed\n", name));
				return False;
			}
			if ((type != SID_NAME_DOM_GRP) &&
			    (type != SID_NAME_ALIAS) &&
			    (type != SID_NAME_WKN_GRP)) {
				DEBUG(5, ("%s is a %s, expected a group\n",
					  name, sid_type_lookup(type)));
				return False;
			}
			if (nt_token_check_sid(&sid, token)) {
				return True;
			}
			continue;
		}
		if (*prefix == '&') {
			if (username) {
				if (user_in_netgroup(sconn, username, name)) {
					return True;
				}
			}
			continue;
		}
		smb_panic("got invalid prefix from do_groups_check");
	}
	return False;
}
예제 #2
0
static NTSTATUS find_forced_group(bool force_user,
				  int snum, const char *username,
				  DOM_SID *pgroup_sid,
				  gid_t *pgid)
{
	NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
	TALLOC_CTX *frame = talloc_stackframe();
	DOM_SID group_sid;
	enum lsa_SidType type;
	char *groupname;
	bool user_must_be_member = False;
	gid_t gid;

	groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
	if (groupname == NULL) {
		DEBUG(1, ("talloc_strdup failed\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (groupname[0] == '+') {
		user_must_be_member = True;
		groupname += 1;
	}

	groupname = talloc_string_sub(talloc_tos(), groupname,
				      "%S", lp_servicename(snum));
	if (groupname == NULL) {
		DEBUG(1, ("talloc_string_sub failed\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (!lookup_name_smbconf(talloc_tos(), groupname,
			 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
			 NULL, NULL, &group_sid, &type)) {
		DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
			   groupname));
		goto done;
	}

	if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
	    (type != SID_NAME_WKN_GRP)) {
		DEBUG(10, ("%s is a %s, not a group\n", groupname,
			   sid_type_lookup(type)));
		goto done;
	}

	if (!sid_to_gid(&group_sid, &gid)) {
		DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
			   sid_string_dbg(&group_sid), groupname));
		goto done;
	}

	/*
	 * If the user has been forced and the forced group starts with a '+',
	 * then we only set the group to be the forced group if the forced
	 * user is a member of that group.  Otherwise, the meaning of the '+'
	 * would be ignored.
	 */

	if (force_user && user_must_be_member) {
		if (user_in_group_sid(username, &group_sid)) {
			sid_copy(pgroup_sid, &group_sid);
			*pgid = gid;
			DEBUG(3,("Forced group %s for member %s\n",
				 groupname, username));
		} else {
			DEBUG(0,("find_forced_group: forced user %s is not a member "
				"of forced group %s. Disallowing access.\n",
				username, groupname ));
			result = NT_STATUS_MEMBER_NOT_IN_GROUP;
			goto done;
		}
	} else {
		sid_copy(pgroup_sid, &group_sid);
		*pgid = gid;
		DEBUG(3,("Forced group %s\n", groupname));
	}

	result = NT_STATUS_OK;
 done:
	TALLOC_FREE(frame);
	return result;
}
예제 #3
0
파일: server_info.c 프로젝트: encukou/samba
NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
			    const char *unix_username,
			    const struct passwd *pwd,
			    struct netr_SamInfo3 **pinfo3,
			    struct extra_auth_info *extra)
{
	struct netr_SamInfo3 *info3;
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx;
	const char *domain_name = NULL;
	const char *user_name = NULL;
	struct dom_sid domain_sid;
	struct dom_sid user_sid;
	struct dom_sid group_sid;
	enum lsa_SidType type;
	uint32_t num_sids = 0;
	struct dom_sid *user_sids = NULL;
	bool is_null;
	bool ok;

	tmp_ctx = talloc_stackframe();

	ok = lookup_name_smbconf(tmp_ctx,
				 unix_username,
				 LOOKUP_NAME_ALL,
				 &domain_name,
				 &user_name,
				 &user_sid,
				 &type);
	if (!ok) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	if (type != SID_NAME_USER) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	ok = winbind_lookup_usersids(tmp_ctx,
				     &user_sid,
				     &num_sids,
				     &user_sids);
	/* Check if winbind is running */
	if (ok) {
		/*
		 * Winbind is running and the first element of the user_sids
		 * is the primary group.
		 */
		if (num_sids > 0) {
			group_sid = user_sids[0];
		}
	} else {
		/*
		 * Winbind is not running, try to create the group_sid from the
		 * passwd group id.
		 */

		/*
		 * This can lead to a primary group of S-1-22-2-XX which
		 * will be rejected by other Samba code.
		 */
		gid_to_sid(&group_sid, pwd->pw_gid);
	}

	/*
	 * If we are a unix group, or a wellknown/builtin alias,
	 * set the group_sid to the
	 * 'Domain Users' RID of 513 which will always resolve to a
	 * name.
	 */
	if (sid_check_is_in_unix_groups(&group_sid) ||
	    sid_check_is_in_builtin(&group_sid) ||
	    sid_check_is_in_wellknown_domain(&group_sid)) {
		if (sid_check_is_in_unix_users(&user_sid)) {
			sid_compose(&group_sid,
				    get_global_sam_sid(),
				    DOMAIN_RID_USERS);
		} else {
			sid_copy(&domain_sid, &user_sid);
			sid_split_rid(&domain_sid, NULL);
			sid_compose(&group_sid,
				    &domain_sid,
				    DOMAIN_RID_USERS);
		}
	}

	/* Make sure we have a valid group sid */
	is_null = is_null_sid(&group_sid);
	if (is_null) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	/* Construct a netr_SamInfo3 from the information we have */
	info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3);
	if (!info3) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	info3->base.account_name.string = talloc_strdup(info3, unix_username);
	if (info3->base.account_name.string == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ZERO_STRUCT(domain_sid);

	status = SamInfo3_handle_sids(unix_username,
				&user_sid,
				&group_sid,
				info3,
				&domain_sid,
				extra);

	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	if (info3->base.domain_sid == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ok = sid_peek_check_rid(&domain_sid, &group_sid,
				&info3->base.primary_gid);
	if (!ok) {
		DEBUG(1, ("The primary group domain sid(%s) does not "
			  "match the domain sid(%s) for %s(%s)\n",
			  sid_string_dbg(&group_sid),
			  sid_string_dbg(&domain_sid),
			  unix_username,
			  sid_string_dbg(&user_sid)));
		status = NT_STATUS_INVALID_SID;
		goto done;
	}

	info3->base.acct_flags = ACB_NORMAL;

	if (num_sids) {
		status = group_sids_to_info3(info3, user_sids, num_sids);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}
	}

	*pinfo3 = talloc_steal(mem_ctx, info3);

	status = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);

	return status;
}