inspec/lib/resources/file.rb

299 lines
9.4 KiB
Ruby
Raw Normal View History

2015-07-15 13:15:18 +00:00
# encoding: utf-8
# copyright: 2015, Vulcano Security GmbH
2016-03-31 00:23:23 +00:00
require 'shellwords'
2015-10-26 03:04:18 +00:00
module Inspec::Resources
module FilePermissionsSelector
def select_file_perms_style(os)
if os.unix?
UnixFilePermissions.new(inspec)
elsif os.windows?
WindowsFilePermissions.new(inspec)
end
end
end
class FileResource < Inspec.resource(1)
include FilePermissionsSelector
include LinuxMountParser
name 'file'
supports platform: 'unix'
supports platform: 'windows'
2015-11-27 13:02:38 +00:00
desc 'Use the file InSpec audit resource to test all system file types, including files, directories, symbolic links, named pipes, sockets, character devices, block devices, and doors.'
example "
describe file('path') do
it { should exist }
it { should be_file }
it { should be_readable }
it { should be_writable }
it { should be_executable.by_user('root') }
2015-11-27 13:02:38 +00:00
it { should be_owned_by 'root' }
its('mode') { should cmp '0644' }
2015-11-27 13:02:38 +00:00
end
"
2016-04-28 16:35:55 +00:00
attr_reader :file, :mount_options
def initialize(path)
# select permissions style
@perms_provider = select_file_perms_style(inspec.os)
2016-04-28 16:35:55 +00:00
@file = inspec.backend.file(path)
end
%w{
type exist? file? block_device? character_device? socket? directory?
2016-04-28 16:35:55 +00:00
symlink? pipe? mode mode? owner owned_by? group grouped_into?
link_path shallow_link_path linked_to? mtime size selinux_label immutable?
2015-09-05 14:07:54 +00:00
product_version file_version version? md5sum sha256sum
path basename source source_path uid gid
}.each do |m|
define_method m.to_sym do |*args|
file.method(m.to_sym).call(*args)
end
end
2016-02-22 03:44:49 +00:00
def content
res = file.content
return nil if res.nil?
res.force_encoding('utf-8')
end
def contain(*_)
raise 'Contain is not supported. Please use standard RSpec matchers.'
end
def readable?(by_usergroup, by_specific_user)
return false unless exist?
return skip_resource '`readable?` is not supported on your OS yet.' if @perms_provider.nil?
file_permission_granted?('read', by_usergroup, by_specific_user)
end
def writable?(by_usergroup, by_specific_user)
return false unless exist?
return skip_resource '`writable?` is not supported on your OS yet.' if @perms_provider.nil?
file_permission_granted?('write', by_usergroup, by_specific_user)
end
def executable?(by_usergroup, by_specific_user)
return false unless exist?
return skip_resource '`executable?` is not supported on your OS yet.' if @perms_provider.nil?
file_permission_granted?('execute', by_usergroup, by_specific_user)
end
Extend Windows ACL matchers (#1744) * Adds alias for 'ListDirectory' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Works with Ruby array of permissions as long as possible Converts to PowerShell array just before use. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Abstracts user-provided permissions to router method Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds FullControl as a specifiable permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds specific permission 'modify' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes #1743 Limits Windows' broad "read" permission to if it can read all of the above, instead of just the first: - File contents - File attributes - File extended attributes - File permissions This better aligns with how Windows names the permissions. 'read' -> Read instead of 'read' -> ReadData Signed-off-by: David Alexander <opensource@thelonelyghost.com> * 'Execute' Windows ACL has alias of 'Traverse' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds 'Delete' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds `should allow('perm').by_user('me')` matcher Provides hooks for later use with Windows ACL matching Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds remaining Windows ACL hooks Skips ReadAndExecute on intentionally since it just aliases the combo of 2 permissions into one new one. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * [Rubocop] Reduces ABC / Cyclomatic complexity Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Reduces global scope with `allows()` -> `be_allowed()` RSpec inferred matchers work nicely here. This changes the `by_user()` and `by()` chained matchers to just be an options hash on the underlying `allowed?()` method. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes integration tests with rename `allows()` -> `be_allowed()` Signed-off-by: David Alexander <opensource@thelonelyghost.com>
2017-10-17 13:01:51 +00:00
def allowed?(permission, opts = {})
return false unless exist?
return skip_resource '`allowed?` is not supported on your OS yet.' if @perms_provider.nil?
file_permission_granted?(permission, opts[:by], opts[:by_user])
end
def mounted?(expected_options = nil, identical = false)
mounted = file.mounted
# return if no additional parameters have been provided
return file.mounted? if expected_options.nil?
# deprecation warning, this functionality will be removed in future version
warn "[DEPRECATION] `be_mounted.with and be_mounted.only_with` are deprecated. Please use `mount('#{source_path}')` instead."
2016-01-02 21:57:52 +00:00
# we cannot read mount data on non-Linux systems
return nil if !inspec.os.linux?
# parse content if we are on linux
@mount_options ||= parse_mount_options(mounted.stdout, true)
if identical
# check if the options should be identical
@mount_options == expected_options
else
# otherwise compare the selected values
@mount_options.contains(expected_options)
end
end
def suid
(mode & 04000) > 0
end
File Resource: add be_setgid, be_setuid, be_sticky matchers (#2104) * Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * TDD Red for setgid/setuid/sticky File matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add documentation for file resource sgid, sticky, and suid matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add matchers to File for setgid, setuid, and sticky by aliasing existing predicates; TDD green Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Rubocop prefers alias to alias_method. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Lint before pushing, of course Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Correct spelling of setgid and setuid matchers in docs Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add be_setgid, be_setuid, be_sticky matcher integration tests for File. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here." This reverts commit 42e672f3b1cea824451f23bb825b486baaa77c02. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "TDD Red for setgid/setuid/sticky File matchers" This reverts commit a4f891fc7e47bad3096b6a1afd6e8f92fb3f8077. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com>
2017-09-03 18:43:13 +00:00
alias setuid? suid
def sgid
(mode & 02000) > 0
end
File Resource: add be_setgid, be_setuid, be_sticky matchers (#2104) * Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * TDD Red for setgid/setuid/sticky File matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add documentation for file resource sgid, sticky, and suid matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add matchers to File for setgid, setuid, and sticky by aliasing existing predicates; TDD green Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Rubocop prefers alias to alias_method. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Lint before pushing, of course Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Correct spelling of setgid and setuid matchers in docs Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add be_setgid, be_setuid, be_sticky matcher integration tests for File. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here." This reverts commit 42e672f3b1cea824451f23bb825b486baaa77c02. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "TDD Red for setgid/setuid/sticky File matchers" This reverts commit a4f891fc7e47bad3096b6a1afd6e8f92fb3f8077. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com>
2017-09-03 18:43:13 +00:00
alias setgid? sgid
def sticky
(mode & 01000) > 0
end
File Resource: add be_setgid, be_setuid, be_sticky matchers (#2104) * Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * TDD Red for setgid/setuid/sticky File matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add documentation for file resource sgid, sticky, and suid matchers Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add matchers to File for setgid, setuid, and sticky by aliasing existing predicates; TDD green Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Rubocop prefers alias to alias_method. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Lint before pushing, of course Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Correct spelling of setgid and setuid matchers in docs Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Add be_setgid, be_setuid, be_sticky matcher integration tests for File. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "Provisioner script to setup resource tests for setgid/setuid/sticky bit tests. This appears to be the correct mechanism per docker_run, but I don't see any other provisioner scripts, so I suspect there is a different Chef-internal mechanism at play here." This reverts commit 42e672f3b1cea824451f23bb825b486baaa77c02. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com> * Revert "TDD Red for setgid/setuid/sticky File matchers" This reverts commit a4f891fc7e47bad3096b6a1afd6e8f92fb3f8077. Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com>
2017-09-03 18:43:13 +00:00
alias sticky? sticky
def to_s
"File #{source_path}"
end
private
def file_permission_granted?(access_type, by_usergroup, by_specific_user)
raise '`file_permission_granted?` is not supported on your OS' if @perms_provider.nil?
2015-12-21 22:12:29 +00:00
if by_specific_user.nil? || by_specific_user.empty?
@perms_provider.check_file_permission_by_mask(file, access_type, by_usergroup, by_specific_user)
else
@perms_provider.check_file_permission_by_user(access_type, by_specific_user, source_path)
end
end
end
class FilePermissions
attr_reader :inspec
def initialize(inspec)
@inspec = inspec
end
end
class UnixFilePermissions < FilePermissions
def permission_flag(access_type)
case access_type
when 'read'
'r'
when 'write'
'w'
when 'execute'
'x'
else
raise 'Invalid access_type provided'
end
end
def usergroup_for(usergroup, specific_user)
if usergroup == 'others'
'other'
elsif (usergroup.nil? || usergroup.empty?) && specific_user.nil?
'all'
else
usergroup
end
end
def check_file_permission_by_mask(file, access_type, usergroup, specific_user)
usergroup = usergroup_for(usergroup, specific_user)
flag = permission_flag(access_type)
mask = file.unix_mode_mask(usergroup, flag)
raise 'Invalid usergroup/owner provided' if mask.nil?
(file.mode & mask) != 0
end
def check_file_permission_by_user(access_type, user, path)
flag = permission_flag(access_type)
if inspec.os.linux?
perm_cmd = "su -s /bin/sh -c \"test -#{flag} #{path}\" #{user}"
elsif inspec.os.bsd? || inspec.os.solaris?
perm_cmd = "sudo -u #{user} test -#{flag} #{path}"
elsif inspec.os.aix?
perm_cmd = "su #{user} -c test -#{flag} #{path}"
elsif inspec.os.hpux?
perm_cmd = "su #{user} -c \"test -#{flag} #{path}\""
else
return skip_resource 'The `file` resource does not support `by_user` on your OS.'
end
cmd = inspec.command(perm_cmd)
cmd.exit_status == 0 ? true : false
end
end
class WindowsFilePermissions < FilePermissions
def check_file_permission_by_mask(_file, _access_type, _usergroup, _specific_user)
raise '`check_file_permission_by_mask` is not supported on Windows'
end
def check_file_permission_by_user(access_type, user, path)
Extend Windows ACL matchers (#1744) * Adds alias for 'ListDirectory' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Works with Ruby array of permissions as long as possible Converts to PowerShell array just before use. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Abstracts user-provided permissions to router method Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds FullControl as a specifiable permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds specific permission 'modify' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes #1743 Limits Windows' broad "read" permission to if it can read all of the above, instead of just the first: - File contents - File attributes - File extended attributes - File permissions This better aligns with how Windows names the permissions. 'read' -> Read instead of 'read' -> ReadData Signed-off-by: David Alexander <opensource@thelonelyghost.com> * 'Execute' Windows ACL has alias of 'Traverse' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds 'Delete' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds `should allow('perm').by_user('me')` matcher Provides hooks for later use with Windows ACL matching Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds remaining Windows ACL hooks Skips ReadAndExecute on intentionally since it just aliases the combo of 2 permissions into one new one. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * [Rubocop] Reduces ABC / Cyclomatic complexity Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Reduces global scope with `allows()` -> `be_allowed()` RSpec inferred matchers work nicely here. This changes the `by_user()` and `by()` chained matchers to just be an options hash on the underlying `allowed?()` method. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes integration tests with rename `allows()` -> `be_allowed()` Signed-off-by: David Alexander <opensource@thelonelyghost.com>
2017-10-17 13:01:51 +00:00
access_rule = translate_perm_names(access_type)
access_rule = convert_to_powershell_array(access_rule)
cmd = inspec.command("@(@((Get-Acl '#{path}').access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.IdentityReference -eq '#{user}' }) | Where-Object {($_.FileSystemRights.ToString().Split(',') | % {$_.trim()} | ? {#{access_rule} -contains $_}) -ne $null}) | measure | % { $_.Count }")
cmd.stdout.chomp == '0' ? false : true
end
Extend Windows ACL matchers (#1744) * Adds alias for 'ListDirectory' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Works with Ruby array of permissions as long as possible Converts to PowerShell array just before use. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Abstracts user-provided permissions to router method Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds FullControl as a specifiable permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds specific permission 'modify' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes #1743 Limits Windows' broad "read" permission to if it can read all of the above, instead of just the first: - File contents - File attributes - File extended attributes - File permissions This better aligns with how Windows names the permissions. 'read' -> Read instead of 'read' -> ReadData Signed-off-by: David Alexander <opensource@thelonelyghost.com> * 'Execute' Windows ACL has alias of 'Traverse' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds 'Delete' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds `should allow('perm').by_user('me')` matcher Provides hooks for later use with Windows ACL matching Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds remaining Windows ACL hooks Skips ReadAndExecute on intentionally since it just aliases the combo of 2 permissions into one new one. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * [Rubocop] Reduces ABC / Cyclomatic complexity Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Reduces global scope with `allows()` -> `be_allowed()` RSpec inferred matchers work nicely here. This changes the `by_user()` and `by()` chained matchers to just be an options hash on the underlying `allowed?()` method. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes integration tests with rename `allows()` -> `be_allowed()` Signed-off-by: David Alexander <opensource@thelonelyghost.com>
2017-10-17 13:01:51 +00:00
private
def convert_to_powershell_array(arr)
if arr.empty?
'@()'
else
%{@('#{arr.join("', '")}')}
end
end
# Translates a developer-friendly string into a list of acceptable
# FileSystemRights that match it, because Windows has a fun heirarchy
# of permissions that are able to be noted in multiple ways.
#
# See also: https://www.codeproject.com/Reference/871338/AccessControl-FileSystemRights-Permissions-Table
def translate_perm_names(access_type)
names = translate_common_perms(access_type)
names ||= translate_granular_perms(access_type)
names ||= translate_uncommon_perms(access_type)
raise 'Invalid access_type provided' unless names
names
Extend Windows ACL matchers (#1744) * Adds alias for 'ListDirectory' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Works with Ruby array of permissions as long as possible Converts to PowerShell array just before use. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Abstracts user-provided permissions to router method Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds FullControl as a specifiable permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds specific permission 'modify' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes #1743 Limits Windows' broad "read" permission to if it can read all of the above, instead of just the first: - File contents - File attributes - File extended attributes - File permissions This better aligns with how Windows names the permissions. 'read' -> Read instead of 'read' -> ReadData Signed-off-by: David Alexander <opensource@thelonelyghost.com> * 'Execute' Windows ACL has alias of 'Traverse' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds 'Delete' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds `should allow('perm').by_user('me')` matcher Provides hooks for later use with Windows ACL matching Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds remaining Windows ACL hooks Skips ReadAndExecute on intentionally since it just aliases the combo of 2 permissions into one new one. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * [Rubocop] Reduces ABC / Cyclomatic complexity Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Reduces global scope with `allows()` -> `be_allowed()` RSpec inferred matchers work nicely here. This changes the `by_user()` and `by()` chained matchers to just be an options hash on the underlying `allowed?()` method. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes integration tests with rename `allows()` -> `be_allowed()` Signed-off-by: David Alexander <opensource@thelonelyghost.com>
2017-10-17 13:01:51 +00:00
end
def translate_common_perms(access_type)
case access_type
when 'full-control'
%w{FullControl}
when 'modify'
translate_perm_names('full-control') + %w{Modify}
when 'read'
translate_perm_names('modify') + %w{ReadAndExecute Read}
when 'write'
translate_perm_names('modify') + %w{Write}
when 'execute'
translate_perm_names('modify') + %w{ReadAndExecute ExecuteFile Traverse}
when 'delete'
translate_perm_names('modify') + %w{Delete}
end
end
def translate_uncommon_perms(access_type)
case access_type
when 'delete-subdirectories-and-files'
translate_perm_names('full-control') + %w{DeleteSubdirectoriesAndFiles}
when 'change-permissions'
translate_perm_names('full-control') + %w{ChangePermissions}
when 'take-ownership'
translate_perm_names('full-control') + %w{TakeOwnership}
when 'synchronize'
translate_perm_names('full-control') + %w{Synchronize}
Extend Windows ACL matchers (#1744) * Adds alias for 'ListDirectory' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Works with Ruby array of permissions as long as possible Converts to PowerShell array just before use. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Abstracts user-provided permissions to router method Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds FullControl as a specifiable permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds specific permission 'modify' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes #1743 Limits Windows' broad "read" permission to if it can read all of the above, instead of just the first: - File contents - File attributes - File extended attributes - File permissions This better aligns with how Windows names the permissions. 'read' -> Read instead of 'read' -> ReadData Signed-off-by: David Alexander <opensource@thelonelyghost.com> * 'Execute' Windows ACL has alias of 'Traverse' Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds 'Delete' permission Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds `should allow('perm').by_user('me')` matcher Provides hooks for later use with Windows ACL matching Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Adds remaining Windows ACL hooks Skips ReadAndExecute on intentionally since it just aliases the combo of 2 permissions into one new one. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * [Rubocop] Reduces ABC / Cyclomatic complexity Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Reduces global scope with `allows()` -> `be_allowed()` RSpec inferred matchers work nicely here. This changes the `by_user()` and `by()` chained matchers to just be an options hash on the underlying `allowed?()` method. Signed-off-by: David Alexander <opensource@thelonelyghost.com> * Fixes integration tests with rename `allows()` -> `be_allowed()` Signed-off-by: David Alexander <opensource@thelonelyghost.com>
2017-10-17 13:01:51 +00:00
end
end
def translate_granular_perms(access_type)
case access_type
when 'write-data', 'create-files'
translate_perm_names('write') + %w{WriteData CreateFiles}
when 'append-data', 'create-directories'
translate_perm_names('write') + %w{CreateDirectories AppendData}
when 'write-extended-attributes'
translate_perm_names('write') + %w{WriteExtendedAttributes}
when 'write-attributes'
translate_perm_names('write') + %w{WriteAttributes}
when 'read-data', 'list-directory'
translate_perm_names('read') + %w{ReadData ListDirectory}
when 'read-attributes'
translate_perm_names('read') + %w{ReadAttributes}
when 'read-extended-attributes'
translate_perm_names('read') + %w{ReadExtendedAttributes}
when 'read-permissions'
translate_perm_names('read') + %w{ReadPermissions}
end
end
end
end