Esempio n. 1
0
liz_acl_t *lzfs_int_convert_fsal_acl(const fsal_acl_t *fsal_acl) {
	liz_acl_t *lzfs_acl = NULL;

	if (!fsal_acl || (!fsal_acl->aces && fsal_acl->naces > 0)) {
		return NULL;
	}

	int count = 0;
	for (unsigned i = 0; i < fsal_acl->naces; ++i) {
		fsal_ace_t *fsal_ace = fsal_acl->aces + i;
		count += (IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace)) ? 1 : 0;
	}

	lzfs_acl = liz_create_acl();
	if (!lzfs_acl) {
		return NULL;
	}

	for (unsigned i = 0; i < fsal_acl->naces; ++i) {
		fsal_ace_t *fsal_ace = fsal_acl->aces + i;
		if (!(IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace))) {
			continue;
		}

		liz_acl_ace_t ace;
		ace.flags = fsal_ace->flag & 0xFF;
		ace.mask = fsal_ace->perm;
		ace.type = fsal_ace->type;
		if (IS_FSAL_ACE_GROUP_ID(*fsal_ace)) {
			ace.id = GET_FSAL_ACE_GROUP(*fsal_ace);
		} else {
			ace.id = GET_FSAL_ACE_USER(*fsal_ace);
		}
		if (IS_FSAL_ACE_SPECIAL_ID(*fsal_ace)) {
			ace.flags |= LIZ_ACL_SPECIAL_WHO;
			switch (GET_FSAL_ACE_USER(*fsal_ace)) {
			case FSAL_ACE_SPECIAL_OWNER:
				ace.id = LIZ_ACL_OWNER_SPECIAL_ID;
				break;
			case FSAL_ACE_SPECIAL_GROUP:
				ace.id = LIZ_ACL_GROUP_SPECIAL_ID;
				break;
			case FSAL_ACE_SPECIAL_EVERYONE:
				ace.id = LIZ_ACL_EVERYONE_SPECIAL_ID;
				break;
			default:
				LogFullDebug(COMPONENT_FSAL, "Invalid FSAL ACE special id type (%d)",
				             (int)GET_FSAL_ACE_USER(*fsal_ace));
				continue;
			}
		}

		liz_add_acl_entry(lzfs_acl, &ace);
	}

	return lzfs_acl;
}
Esempio n. 2
0
int display_fsal_ace(struct display_buffer *dspbuf, int ace_number,
		     fsal_ace_t *pace, bool is_dir)
{
	int b_left;

	if (!pace)
		return display_cat(dspbuf, "ACE: <NULL>");

	/* Print the entire ACE. */
	b_left = display_printf(dspbuf, "ACE %d:", ace_number);

	/* ACE type. */
	if (b_left > 0)
		b_left =
		    display_cat(dspbuf,
				IS_FSAL_ACE_ALLOW(*pace) ? " allow" :
				IS_FSAL_ACE_DENY(*pace) ? " deny" :
				IS_FSAL_ACE_AUDIT(*pace) ? " audit" : " ?");

	/* ACE who and its type. */
	if (b_left > 0 && IS_FSAL_ACE_SPECIAL_ID(*pace))
		b_left =
		    display_cat(dspbuf,
				IS_FSAL_ACE_SPECIAL_OWNER(*pace) ? " owner@" :
				IS_FSAL_ACE_SPECIAL_GROUP(*pace) ? " group@" :
				IS_FSAL_ACE_SPECIAL_EVERYONE(*pace) ?
				" everyone@" : "");

	if (b_left > 0 && !IS_FSAL_ACE_SPECIAL_ID(*pace)) {
		if (IS_FSAL_ACE_SPECIAL_ID(*pace))
			b_left =
			    display_printf(dspbuf, " gid %d", pace->who.gid);
		else
			b_left =
			    display_printf(dspbuf, " uid %d", pace->who.uid);
	}

	/* ACE mask. */
	if (b_left > 0)
		b_left = display_fsal_v4mask(dspbuf, pace->perm, is_dir);

	/* ACE Inherit flags. */
	if (b_left > 0 && IS_FSAL_ACE_INHERIT(*pace))
		b_left = display_fsal_inherit_flags(dspbuf, pace);

	return b_left;
}
Esempio n. 3
0
static void fsal_print_ace(int ace_number, fsal_ace_t *pace, char *p_acebuf)
{
  char inherit_flags[ACL_DEBUG_BUF_SIZE];

  if(!pace || !p_acebuf)
    return;

  memset(p_acebuf, 0, ACL_DEBUG_BUF_SIZE);
  memset(inherit_flags, 0, ACL_DEBUG_BUF_SIZE);

  /* Get inherit flags if any. */
  fsal_print_inherit_flags(pace, inherit_flags);

  /* Print the entire ACE. */
  sprintf(p_acebuf, "ACE %d %s %s %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c %s",
          ace_number,
          /* ACE type. */
          IS_FSAL_ACE_ALLOW(*pace)? "allow":
          IS_FSAL_ACE_DENY(*pace) ? "deny":
          IS_FSAL_ACE_AUDIT(*pace)? "audit": "?",
          /* ACE who and its type. */
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_OWNER(*pace))    ? "owner@":
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_GROUP(*pace))    ? "group@":
          (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_EVERYONE(*pace)) ? "everyone@":
          IS_FSAL_ACE_SPECIAL_ID(*pace)						 ? "specialid":
          IS_FSAL_ACE_GROUP_ID(*pace) 						 ? "gid": "uid",
          GET_FSAL_ACE_WHO(*pace),
          /* ACE mask. */
          IS_FSAL_ACE_READ_DATA(*pace)		 ? 'r':'-',
          IS_FSAL_ACE_WRITE_DATA(*pace)		 ? 'w':'-',
          IS_FSAL_ACE_EXECUTE(*pace)		 ? 'x':'-',
          IS_FSAL_ACE_ADD_SUBDIRECTORY(*pace)    ? 'm':'-',
          IS_FSAL_ACE_READ_NAMED_ATTR(*pace)	 ? 'n':'-',
          IS_FSAL_ACE_WRITE_NAMED_ATTR(*pace) 	 ? 'N':'-',
          IS_FSAL_ACE_DELETE_CHILD(*pace) 	 ? 'p':'-',
          IS_FSAL_ACE_READ_ATTR(*pace)		 ? 't':'-',
          IS_FSAL_ACE_WRITE_ATTR(*pace)		 ? 'T':'-',
          IS_FSAL_ACE_DELETE(*pace)		 ? 'd':'-',
          IS_FSAL_ACE_READ_ACL(*pace) 		 ? 'c':'-',
          IS_FSAL_ACE_WRITE_ACL(*pace)		 ? 'C':'-',
          IS_FSAL_ACE_WRITE_OWNER(*pace)	 ? 'o':'-',
          IS_FSAL_ACE_SYNCHRONIZE(*pace)	 ? 'z':'-',
          /* ACE Inherit flags. */
          IS_FSAL_ACE_INHERIT(*pace)? inherit_flags: "");
}
Esempio n. 4
0
static fsal_status_t fsal_check_access_acl(struct user_cred *creds,
					   fsal_aceperm_t v4mask,
					   fsal_accessflags_t *allowed,
					   fsal_accessflags_t *denied,
					   struct attrlist *p_object_attributes)
{
	fsal_aceperm_t missing_access;
	fsal_aceperm_t tperm;
	uid_t uid;
	gid_t gid;
	fsal_acl_t *pacl = NULL;
	fsal_ace_t *pace = NULL;
	int ace_number = 0;
	bool is_dir = false;
	bool is_owner = false;
	bool is_group = false;
	bool is_root = false;

	if (allowed != NULL)
		*allowed = 0;

	if (denied != NULL)
		*denied = 0;

	if (!p_object_attributes->acl) {
		/* Means that FSAL_ACE4_REQ_FLAG was set, but no ACLs */
		LogFullDebug(COMPONENT_NFS_V4_ACL,
			     "Allow ACE required, but no ACLs");
		return fsalstat(ERR_FSAL_NO_ACE, 0);
	}

	/* unsatisfied flags */
	missing_access = v4mask & ~FSAL_ACE4_PERM_CONTINUE;
	if (!missing_access) {
		LogFullDebug(COMPONENT_NFS_V4_ACL, "Nothing was requested");
		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	}

	/* Get file ownership information. */
	uid = p_object_attributes->owner;
	gid = p_object_attributes->group;
	pacl = p_object_attributes->acl;
	is_dir = (p_object_attributes->type == DIRECTORY);
	is_root = creds->caller_uid == 0;

	if (is_root) {
		if (is_dir) {
			if (allowed != NULL)
				*allowed = v4mask;

			/* On a directory, allow root anything. */
			LogFullDebug(COMPONENT_NFS_V4_ACL,
				     "Met root privileges on directory");
			return fsalstat(ERR_FSAL_NO_ERROR, 0);
		}

		/* Otherwise, allow root anything but execute. */
		missing_access &= FSAL_ACE_PERM_EXECUTE;

		if (allowed != NULL)
			*allowed = v4mask & ~FSAL_ACE_PERM_EXECUTE;

		if (!missing_access) {
			LogFullDebug(COMPONENT_NFS_V4_ACL,
				     "Met root privileges");
			return fsalstat(ERR_FSAL_NO_ERROR, 0);
		}
	}

	LogFullDebug(COMPONENT_NFS_V4_ACL,
		     "file acl=%p, file uid=%u, file gid=%u, ", pacl, uid, gid);

	if (isFullDebug(COMPONENT_NFS_V4_ACL)) {
		char str[LOG_BUFF_LEN];
		struct display_buffer dspbuf = { sizeof(str), str, str };

		(void)display_fsal_v4mask(&dspbuf, v4mask,
					  p_object_attributes->type ==
					  DIRECTORY);

		LogFullDebug(COMPONENT_NFS_V4_ACL,
			     "user uid=%u, user gid= %u, v4mask=%s",
			     creds->caller_uid, creds->caller_gid, str);
	}

	is_owner = fsal_check_ace_owner(uid, creds);
	is_group = fsal_check_ace_group(gid, creds);

	/* Always grant READ_ACL, WRITE_ACL and READ_ATTR, WRITE_ATTR
	 * to the file owner. */
	if (is_owner) {
		if (allowed != NULL)
			*allowed |=
			    v4mask & (FSAL_ACE_PERM_WRITE_ACL |
				      FSAL_ACE_PERM_READ_ACL |
				      FSAL_ACE_PERM_WRITE_ATTR |
				      FSAL_ACE_PERM_READ_ATTR);

		missing_access &=
		    ~(FSAL_ACE_PERM_WRITE_ACL | FSAL_ACE_PERM_READ_ACL);
		missing_access &=
		    ~(FSAL_ACE_PERM_WRITE_ATTR | FSAL_ACE_PERM_READ_ATTR);
		if (!missing_access) {
			LogFullDebug(COMPONENT_NFS_V4_ACL,
				     "Met owner privileges");
			return fsalstat(ERR_FSAL_NO_ERROR, 0);
		}
	}
	/** @todo Even if user is admin, audit/alarm checks should be done. */

	for (pace = pacl->aces; pace < pacl->aces + pacl->naces; pace++) {
		ace_number += 1;

		LogFullDebug(COMPONENT_NFS_V4_ACL,
			     "ace numnber: %d ace type 0x%X perm 0x%X flag 0x%X who %u",
			     ace_number, pace->type, pace->perm, pace->flag,
			     GET_FSAL_ACE_WHO(*pace));

		/* Process Allow and Deny entries. */
		if (!IS_FSAL_ACE_ALLOW(*pace) && !IS_FSAL_ACE_DENY(*pace)) {
			LogFullDebug(COMPONENT_NFS_V4_ACL, "not allow or deny");
			continue;
		}

		LogFullDebug(COMPONENT_NFS_V4_ACL, "allow or deny");

		/* Check if this ACE is applicable. */
		if (fsal_check_ace_applicable(pace, creds, is_dir, is_owner,
					      is_group, is_root)) {
			if (IS_FSAL_ACE_ALLOW(*pace)) {
				/* Do not set bits which are already denied */
				if (denied)
					tperm = pace->perm & ~*denied;
				else
					tperm = pace->perm;

				LogFullDebug(COMPONENT_NFS_V4_ACL,
					     "allow perm 0x%X remainingPerms 0x%X",
					     tperm, missing_access);

				if (allowed != NULL)
					*allowed |= v4mask & tperm;

				missing_access &=
				    ~(tperm & missing_access);

				if (!missing_access) {
					fsal_print_access_by_acl(
							pacl->naces,
							ace_number,
							pace,
							v4mask,
							ERR_FSAL_NO_ERROR,
							is_dir,
							creds);
					break;
				}
			} else if ((pace->perm & missing_access) && !is_root) {
				fsal_print_access_by_acl(
					pacl->naces,
					ace_number,
					pace,
					v4mask,
#ifndef ENABLE_RFC_ACL
					(pace->perm & missing_access &
					 (FSAL_ACE_PERM_WRITE_ATTR |
					  FSAL_ACE_PERM_WRITE_ACL |
					  FSAL_ACE_PERM_WRITE_OWNER))
					    != 0 ?
					    ERR_FSAL_PERM :
#endif /* ENABLE_RFC_ACL */
					    ERR_FSAL_ACCESS,
					is_dir,
					creds);

				if (denied != NULL)
					*denied |= v4mask & pace->perm;
				if (denied == NULL ||
				    (v4mask &
				     FSAL_ACE4_PERM_CONTINUE) == 0) {
#ifndef ENABLE_RFC_ACL
					if ((pace->perm & missing_access &
					    (FSAL_ACE_PERM_WRITE_ATTR |
					     FSAL_ACE_PERM_WRITE_ACL |
					     FSAL_ACE_PERM_WRITE_OWNER))
					    != 0) {
						LogDebug(COMPONENT_NFS_V4_ACL,
							 "access denied (EPERM)");
						return fsalstat(ERR_FSAL_PERM,
							0);
					} else {
						LogDebug(COMPONENT_NFS_V4_ACL,
							 "access denied (EACCESS)");
						return fsalstat(ERR_FSAL_ACCESS,
							0);
					}
#else /* ENABLE_RFC_ACL */
					LogDebug(COMPONENT_NFS_V4_ACL,
						 "access denied (EACCESS)");
					return fsalstat(ERR_FSAL_ACCESS, 0);
#endif /* ENABLE_RFC_ACL */
				}

				missing_access &=
				    ~(pace->perm & missing_access);

				/* If this DENY ACE blocked the last
				 * remaining requested access
				 * bits, break out of the loop because
				 * we're done and don't
				 * want to evaluate any more ACEs.
				 */
				if (!missing_access)
					break;
			}
		}
	}

	if (IS_FSAL_ACE4_REQ(v4mask) && missing_access) {
		LogDebug(COMPONENT_NFS_V4_ACL, "final access unknown (NO_ACE)");
		return fsalstat(ERR_FSAL_NO_ACE, 0);
	} else if (missing_access || (denied != NULL && *denied != 0)) {
#ifndef ENABLE_RFC_ACL
		if ((missing_access &
		     (FSAL_ACE_PERM_WRITE_ATTR | FSAL_ACE_PERM_WRITE_ACL |
		      FSAL_ACE_PERM_WRITE_OWNER)) != 0) {
			LogDebug(COMPONENT_NFS_V4_ACL,
				 "final access denied (EPERM)");
			return fsalstat(ERR_FSAL_PERM, 0);
		} else {
			LogDebug(COMPONENT_NFS_V4_ACL,
				 "final access denied (EACCESS)");
			return fsalstat(ERR_FSAL_ACCESS, 0);
		}
#else /* ENABLE_RFC_ACL */
		LogDebug(COMPONENT_NFS_V4_ACL, "final access denied (EACCESS)");
		return fsalstat(ERR_FSAL_ACCESS, 0);
#endif /* ENABLE_RFC_ACL */
	} else {
		LogFullDebug(COMPONENT_NFS_V4_ACL, "access granted");
		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	}
}
Esempio n. 5
0
static fsal_status_t fsal_check_access_acl(fsal_op_context_t * p_context,   /* IN */
                                                  fsal_aceperm_t v4mask,  /* IN */
                                                  fsal_attrib_list_t * p_object_attributes   /* IN */ )
{
  fsal_aceperm_t missing_access;
  fsal_uid_t uid;
  fsal_gid_t gid;
  fsal_acl_t *pacl = NULL;
  fsal_ace_t *pace = NULL;
  int ace_number = 0;
  fsal_boolean_t is_dir = FALSE;
  fsal_boolean_t is_owner = FALSE;
  fsal_boolean_t is_group = FALSE;

  /* unsatisfied flags */
  missing_access = v4mask;
  if(!missing_access)
    {
      LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: Nothing was requested");
      ReturnCode(ERR_FSAL_NO_ERROR, 0);
    }

  /* Get file ownership information. */
  uid = p_object_attributes->owner;
  gid = p_object_attributes->group;
  pacl = p_object_attributes->acl;
  is_dir = (p_object_attributes->type == FSAL_TYPE_DIR);

  LogDebug(COMPONENT_FSAL,
           "fsal_check_access_acl: file acl=%p, file uid=%d, file gid= %d",
           pacl,uid, gid);
  LogDebug(COMPONENT_FSAL,
           "fsal_check_access_acl: user uid=%d, user gid= %d, v4mask=0x%X",
           p_context->credential.user,
           p_context->credential.group,
           v4mask);

  is_owner = fsal_check_ace_owner(uid, p_context);
  is_group = fsal_check_ace_group(gid, p_context);

  /* Always grant READ_ACL, WRITE_ACL and READ_ATTR, WRITE_ATTR to the file
   * owner. */
  if(is_owner)
    {
      missing_access &= ~(FSAL_ACE_PERM_WRITE_ACL | FSAL_ACE_PERM_READ_ACL);
      missing_access &= ~(FSAL_ACE_PERM_WRITE_ATTR | FSAL_ACE_PERM_READ_ATTR);
      if(!missing_access)
        {
          LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: Met owner privileges");
          ReturnCode(ERR_FSAL_NO_ERROR, 0);
        }
    }

  // TODO: Even if user is admin, audit/alarm checks should be done.

  ace_number = 1;
  for(pace = pacl->aces; pace < pacl->aces + pacl->naces; pace++)
    {
      LogDebug(COMPONENT_FSAL,
               "fsal_check_access_acl: ace type 0x%X perm 0x%X flag 0x%X who %d",
               pace->type, pace->perm, pace->flag, GET_FSAL_ACE_WHO(*pace));

      /* Process Allow and Deny entries. */
      if(IS_FSAL_ACE_ALLOW(*pace) || IS_FSAL_ACE_DENY(*pace))
        {
          LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: allow or deny");

          /* Check if this ACE is applicable. */
          if(fsal_check_ace_applicable(pace, p_context, is_dir, is_owner, is_group))
            {
              if(IS_FSAL_ACE_ALLOW(*pace))
                {
                  LogDebug(COMPONENT_FSAL,
                           "fsal_check_access_acl: allow perm 0x%X remainingPerms 0x%X",
                           pace->perm, missing_access);

                  missing_access &= ~(pace->perm & missing_access);
                  if(!missing_access)
                    {
                      LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: access granted");
                      fsal_print_access_by_acl(pacl->naces, ace_number, pace,
                                                     v4mask, ERR_FSAL_NO_ERROR, is_dir, p_context);
                      ReturnCode(ERR_FSAL_NO_ERROR, 0);
                    }
                }
             else if(pace->perm & missing_access)
               {
                 LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: access denied");
                 fsal_print_access_by_acl(pacl->naces, ace_number, pace, v4mask,
                                                ERR_FSAL_ACCESS, is_dir, p_context);
                 ReturnCode(ERR_FSAL_ACCESS, 0);
               }
            }
        }

        ace_number += 1;
    }

  if(missing_access)
    {
      LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: access denied");
      ReturnCode(ERR_FSAL_ACCESS, 0);
    }
  else
    {
      LogDebug(COMPONENT_FSAL, "fsal_check_access_acl: access granted");
      ReturnCode(ERR_FSAL_NO_ERROR, 0);
    }

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}